Bash for loop打印出意外的输出,那是为什么? [英] Bash for loop prints unexpected output, why is that?
问题描述
我编写了一个脚本,该脚本查询AWS Route53上的dns区域并返回特定服务器的IP.
I wrote a script which queries a dns zone on AWS Route53 and returns IP's of specific servers.
目标是在启动CloudFormation堆栈后运行此脚本,并且该脚本将使用更新的服务器IP更新我的本地~/.ssh/config
文件.
The aim is to run this script after starting a CloudFormation stack and that the script will update my local ~/.ssh/config
file with the updated servers IP's.
我想捕获"配置中以HostName开头但与我要编辑的服务器的主机名相关的行,因此我运行了以下命令:
I want to "catch" the line in the config which starts with HostName but related to the hostname of the server I would like to edit and so I've ran the following command:
$ grep -A2 dev-api2.company-private ~/.ssh/config
Host dev-api2.company-private
User ec2-user
HostName 5.5.5.5
接下来,我跑了:
$ for line in $(grep -A2 dev-api2.company-private ~/.ssh/config); do echo $line ; done
Host
dev-api2.company-private
User
ec2-user
HostName
5.5.5.5
由于某种原因,输出的打印结果不符合我的预期,它把每个单词都打到了单独的一行,但是为什么会发生呢?
For some reason the output is printed not as I expected, it broke each word to a separate line, but why does it happen?
编辑#1: 我的想法是做这样的事情:
Edit #1: My idea was to do something like that:
for line in $(grep -A2 dev-api2.company-private ~/.ssh/config)
do
if [[ $line == "^HostName.*" ]]
then
sed -i 's!$line!HostName 1.1.1.1!g' ~/.ssh/config
fi
done
编辑#2:
好的,因此~/.ssh/config
文件的相关部分如下所示:
Edit #2:
Ok, so the relevant portion of the ~/.ssh/config
file looks like that:
Host as-bastion
User ec2-user
HostName ec2-34.us-west-2.compute.amazonaws.com
IdentityFile ~/.ssh/company/bastion.pem
Host dev-api1.company-private
User ec2-user
HostName 172.51.24.171
IdentityFile ~/.ssh/company/company.pem
ProxyCommand ssh ec2-user@as-bastion -W %h:%p
Host dev-api2.company-private
User ec2-user
HostName 172.51.25.248
IdentityFile ~/.ssh/company/company.pem
ProxyCommand ssh ec2-user@as-bastion -W %h:%p
该文件包含许多类似上述的块,但是我只希望对包含我在grep中使用过的字符串(dev-api2.company-private)"的块的"HostName"行进行sed.
The file contains many blocks like the ones above, but I want to sed only the "HostName" lines of blocks which contain the string I've used in the grep (dev-api2.company-private).
@anubhava:您的答案中的代码更改了包含字符串"HostName"的行,即使这些块与"dev-api2.company-private"无关.
@anubhava: The code in your answer changed lines containing the string "HostName" even in blocks which are not related to "dev-api2.company-private".
怎么办?
推荐答案
您应该在使用进程替换的while read
循环,而不是使用命令替换的for
循环:
You should be using this while read
loop using process substitution instead of a for
loop using command substitution:
while IFS= read -r line; do
echo "$line"
done < <(grep -A2 dev-api2.company-private ~/.ssh/config)
根据您的评论,我建议最好像这样使用awk
:
awk -v ORS='\n\n' -v RS= -v api='^Host dev-api2' -v ip='1.1.1.1' '
$0 ~ api "\\.company-private$" {sub(/\nHostName [^\n]+/, "\nHostName " ip)} 1' ~/.ssh/config
要保存更改,请使用以下awk
命令:
To save changes use this awk
command:
awk -v ORS='\n\n' -v RS= -v api='^Host dev-api2' -v ip='1.1.1.1' '
$0 ~ api "\\.company-private$" {sub(/\nHostName [^\n]+/, "\nHostName " ip)} 1
' ~/.ssh/config > $$.tmp && mv $$.tmp ~/.ssh/config
这里有一个班轮机sed
做同样的工作:
Here is one liner sed
to do the same job:
sed -i.bak '/dev-api2\.company-private/{N;p;N;s/.*/HostName 1.1.1.1/;}' ~/.ssh/config
这篇关于Bash for loop打印出意外的输出,那是为什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!