Bash 如何迭代awk结果

Bash 如何迭代awk结果,bash,awk,Bash,Awk,我有以下字符串,我只想检索eu-central-1的特定ID: ca-central-1:ami aaaa,eu-central-1:ami BBBBBB,eu-north-1:ami cccc,eu-west-1:ami dddd 所以我想要的输出是:amibbbb 我现在的做法是: echo a-central-1:ami-aaaa,eu-central-1:ami-bbbb,eu-north-1:ami-cccc,eu-west-1:ami-dddd | awk -F',' '{ prin

我有以下字符串,我只想检索eu-central-1的特定ID:

ca-central-1:ami aaaa,eu-central-1:ami BBBBBB,eu-north-1:ami cccc,eu-west-1:ami dddd

所以我想要的输出是:amibbbb

我现在的做法是:

echo a-central-1:ami-aaaa,eu-central-1:ami-bbbb,eu-north-1:ami-cccc,eu-west-1:ami-dddd |
awk -F',' '{ print $2 }' |
awk -F':' '{print $2}'
这种方法的问题是,我明确指定eu-central-1是第一个awk调用的第二个$2结果,但有时它们可能以不同的顺序出现,因此我可能需要迭代这个结果。是否可以在一行中实现这一点,并且事先不知道eu-central-1:ami BBBBBB将在字符串中的哪个位置着陆?

像这样使用grep:

在这里,grep使用以下选项: -P:使用Perl正则表达式。 -o:仅打印匹配项,每行打印一个匹配项,而不是整行

\b:单词边界。 \K:假设比赛从这一点开始。具体来说,在打印匹配项时忽略正则表达式的前面部分。 [^,]+:非逗号的任何字符,一次或多次出现

另见: 像这样使用grep:

在这里,grep使用以下选项: -P:使用Perl正则表达式。 -o:仅打印匹配项,每行打印一个匹配项,而不是整行

\b:单词边界。 \K:假设比赛从这一点开始。具体来说,在打印匹配项时忽略正则表达式的前面部分。 [^,]+:非逗号的任何字符,一次或多次出现

另见:

我更喜欢格雷普。但为了完整起见,这里有一个替代方案:

默认情况下,可以设置awk的记录分隔符linebreak,然后仅打印以eu-central-1开头的记录

我更喜欢格雷普。但为了完整起见,这里有一个替代方案:

默认情况下,可以设置awk的记录分隔符linebreak,然后仅打印以eu-central-1开头的记录

有一个想法:

其中:

-En-启用扩展正则表达式支持 ^.*-[capture group 1]-匹配行首加上以逗号结尾的零个或多个字符实例, ^*${id}:-捕获组1后跟${id}+: [^,]*-[capture group 2]-将所有内容匹配到下一个逗号,但不包括下一个逗号, ,.*$-[capture group 3]-将零个或多个逗号实例后跟其他字符匹配到行尾 \2/p-打印捕获组2 或者,使用here字符串消除管道/子流程调用:

id='eu-central-1'

# desired id at start of input string:

sed -En "s/^(.*,)*${id}:([^,]*)(,.*)*$/\2/p"  <<< 'eu-central-1:ami-bbbb,a-central-1:ami-aaaa,eu-north-1:ami-cccc,eu-west-1:ami-dddd'

# desired id at end of input string:

sed -En "s/^(.*,)*${id}:([^,]*)(,.*)*$/\2/p"  <<< 'a-central-1:ami-aaaa,eu-north-1:ami-cccc,eu-west-1:ami-dddd,eu-central-1:ami-bbbb'
有一个想法:

其中:

-En-启用扩展正则表达式支持 ^.*-[capture group 1]-匹配行首加上以逗号结尾的零个或多个字符实例, ^*${id}:-捕获组1后跟${id}+: [^,]*-[capture group 2]-将所有内容匹配到下一个逗号,但不包括下一个逗号, ,.*$-[capture group 3]-将零个或多个逗号实例后跟其他字符匹配到行尾 \2/p-打印捕获组2 或者,使用here字符串消除管道/子流程调用:

id='eu-central-1'

# desired id at start of input string:

sed -En "s/^(.*,)*${id}:([^,]*)(,.*)*$/\2/p"  <<< 'eu-central-1:ami-bbbb,a-central-1:ami-aaaa,eu-north-1:ami-cccc,eu-west-1:ami-dddd'

# desired id at end of input string:

sed -En "s/^(.*,)*${id}:([^,]*)(,.*)*$/\2/p"  <<< 'a-central-1:ami-aaaa,eu-north-1:ami-cccc,eu-west-1:ami-dddd,eu-central-1:ami-bbbb'
将$1定义为行记录分隔符和:字段分隔符,一个简单的条件将打印结果

echo -n a-central-1:ami-aaaa,eu-central-1:ami-bbbb,eu-north-1:ami-cccc,eu-west-1:ami-dddd |
awk 'BEGIN{RS=","; FS=":"}$1=="eu-central-1"{print $2}'
将$1定义为行记录分隔符和:字段分隔符,一个简单的条件将打印结果

echo -n a-central-1:ami-aaaa,eu-central-1:ami-bbbb,eu-north-1:ami-cccc,eu-west-1:ami-dddd |
awk 'BEGIN{RS=","; FS=":"}$1=="eu-central-1"{print $2}'

GNU sed或OSX/BSD sed用于-E:


GNU sed或OSX/BSD sed用于-E:


如果您的grep不支持-P且您没有pcregremp,请删除\K并附加| cut-d:-f2。如果您的grep不支持-P且您没有pcregremp,请删除\K并附加| cut-d:-f2。如果eu-central-1:foo是输入行上的最后一个内容,则会打印额外的换行。谢谢您的提示。如果出现这样的问题,您可以使用RS=',|\n'来修复它。但我不确定输入格式。可能在单个字段中允许使用换行符作为常规符号。OP必须对此做出决定。但是,根据输入的不同,最确定的是在最末尾总是有一个换行符。是的,您可以使用RS='、|\n'甚至只是RS='[,\n]',但这可能是特定于gawk的,这可能是可以的。如果输入行上的最后一个内容是eu-central-1:foo,则会打印额外的换行符。谢谢您的提示。如果出现这样的问题,您可以使用RS=',|\n'来修复它。但我不确定输入格式。可能在单个字段中允许使用换行符作为常规符号。OP必须对此做出决定。但是,根据输入的不同,最确定的是在最末端总是有一个换行符。是的,您可以使用RS='、|\n'甚至只是RS='[,\n]不过,如果输入行中的eu-central-1:foo是最后一件事,那么它可能会额外打印一行新词,这与10小时前的答案是一样的。我没有注意到他的回答。你的意思是它也会打印foo?我无意处理多次出现的eu-central-1,但它可以很容易地修复。不,我的意思是它将打印foo\n\n而不仅仅是foo\n,因为输入末尾的\n将是$2的一部分,因为它不作为RS使用,而RS是,。你可以把它修好
th RS=[,\n]如果您有GNU awk。我很高兴您注意到这一点,谢谢!没有必要更改代码。只需在echo中添加-n参数就可以避免这个问题。不客气。这只会产生一个新问题,因为根据POSIX,echo输出的不是有效的文本行,所有行都必须以换行结束,因此您正在创建未定义的行为,试图在其上运行文本处理工具。您可以解决echo“foo”的问题,以确保字符串以逗号结尾。这与10小时前的答案相同,因此存在相同的问题,即如果eu-central-1:foo是输入行上的最后一个内容,它将打印额外的换行符。确实如此。我没有注意到他的回答。你的意思是它也会打印foo?我无意处理多次出现的eu-central-1,但它可以很容易地修复。不,我的意思是它将打印foo\n\n而不仅仅是foo\n,因为输入末尾的\n将是$2的一部分,因为它不作为RS使用,而RS是,。如果您有GNU awk,您可以用RS=[,\n]来修复它。很高兴您注意到了这一点,谢谢!没有必要更改代码。只需在echo中添加-n参数就可以避免这个问题。不客气。这只会产生一个新问题,因为根据POSIX,echo输出的不是有效的文本行,所有行都必须以换行结束,因此您正在创建未定义的行为,试图在其上运行文本处理工具。您可以使用echo'foo'解决这个问题,以确保字符串以逗号结尾。
ami-bbbb
echo -n a-central-1:ami-aaaa,eu-central-1:ami-bbbb,eu-north-1:ami-cccc,eu-west-1:ami-dddd |
awk 'BEGIN{RS=","; FS=":"}$1=="eu-central-1"{print $2}'
$ sed -E 's/(^|.*,)eu-central-1:([^,]*).*/\2/' file
ami-bbbb