我的 Ubuntu 系统上的命令打印以下输出,我将输出保存到变量 $problem_dbs 中:
tacservices/e43ccb05-5b0a-4403-950b-9c91ed3f3694 unresponsive agent z1 10.213.197.77 tac-nightly-test tacservices/54be8202-2304-462e-8574-1aef379160d9 failing z1 10.213.204.228 tac-Trip-test
我想搜索并打印以 'tac-*' 开头的字符串:
tac-nightly-test
tac-Trip-test
我试过了:
echo $problem_dbs | sed -n -e 's/^.*\(tac-\)/\1/p'
但它只打印tac-Trip-test
我错过了什么吗?
答案1
如果您的 awk 版本支持没有终止换行符的输入(据我所知都是如此),那么您需要的是:
printf '%s' "$problem_dbs" | awk -v RS=' ' '/^tac-/'
tac-nightly-test
tac-Trip-test
否则,使用 GNU awk 进行多字符RS
和\s
:
awk -v RS='\\s' '/^tac-/'
或使用任何 awk (假设您有单行输入,如问题中所示,并且永远不会tac-
在一行末尾有一个字符串的多行输入,然后立即在下一行的开头再次输入):
awk -v RS=' ' '{sub(/\n/,"")} /^tac-/'
答案2
您的 sed 命令意味着“不要打印任何内容 ( ) ,除非您可以用自身-n
替换从行开头到最后一次出现的所有内容”。tac-
所以你要删除最后一个之前的所有内容tac-
然后打印,所以你只能得到tac-Trip-test
.
由于sed
不进行“非贪婪”匹配,这意味着.*
将始终匹配最长的可能字符串。然而,其他工具可以进行非贪婪匹配:
GNU
grep
$ echo "$problem_dbs" | grep -oP '(^|\s)\Ktac-\S+' tac-nightly-test tac-Trip-test
珀尔
$ echo "$problem_dbs" | perl -lane 'print join "\n",grep{/^tac-\S+/}@F' tac-nightly-test tac-Trip-test
各种各样的
$ echo "$problem_dbs" | tr ' ' '\n' | grep '^tac-' tac-nightly-test tac-Trip-test
答案3
和awk
:
$ echo "$problem_dbs" | awk '
{for(i=1;i<=NF;i++)
if ($i ~ /^tac-/)
print $(i)
}'
tac-nightly-test
tac-Trip-test