匹配字符串的一部分并打印整个字符串

匹配字符串的一部分并打印整个字符串

我的 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不进行“非贪婪”匹配,这意味着.*将始终匹配最长的可能字符串。然而,其他工具可以进行非贪婪匹配:

  1. GNUgrep

    $ echo "$problem_dbs" | grep -oP '(^|\s)\Ktac-\S+'
    tac-nightly-test
    tac-Trip-test
    
  2. 珀尔

    $ echo "$problem_dbs" | perl -lane 'print join "\n",grep{/^tac-\S+/}@F'
    tac-nightly-test
    tac-Trip-test
    
  3. 各种各样的

    $ 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

相关内容