Bash for loop打印出意外的输出,那是为什么? [英] Bash for loop prints unexpected output, why is that?

查看:64
本文介绍了Bash for loop打印出意外的输出,那是为什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我编写了一个脚本,该脚本查询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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆