Bash for loop打印出意想不到的输出,为什么会这样?

时间:2017-10-30 18:47:49

标签: bash awk sed

我编写了一个脚本,用于查询AWS Route53上的dns区域并返回特定服务器的IP。

目标是在启动CloudFormation堆栈后运行此脚本,并且脚本将使用更新的服务器IP更新我的本地~/.ssh/config文件。

我想“捕获”配置中的行,该行以HostName开头但与我想要编辑的服务器的主机名相关,因此我运行了以下命令:

$ 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

由于某种原因,输出的打印效果并不像我预期的那样,它会将每个单词分成一个单独的行,但为什么会这样?

编辑#1: 我的想法是做那样的事情:

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文件的相关部分看起来像这样:

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中使用的字符串的块的“HostName”行(dev-api2.company-private)。

@anubhava:答案中的代码更改了包含字符串“HostName”的行,即使在与“dev-api2.company-private”无关的块中也是如此。

怎么做?

1 个答案:

答案 0 :(得分:6)

您应该使用进程替换而不是使用命令替换while read循环来使用此for循环:

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命令:

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

sed -i.bak '/dev-api2\.company-private/{N;p;N;s/.*/HostName 1.1.1.1/;}' ~/.ssh/config