2

我有以下文字:

aaa rr tt zz pp
aaa pp xx yy uu zz

并且需要提取所有 'aaa'、'zz' 和 'xx' 模式并将它们打印在一行上,如下所示:

aaa zz
aaa xx zz

我发现最好的是grep -oP 'aaa|xx|zz',但这会返回在新行上找到的每个模式:

aaa
zz
aaa
xx
zz

我试图添加类似的东西,tr -d '\n'但在这种情况下,它会在单行上返回整个匹配项,这不是我想要的。

注意:我需要一个支持正则表达式和非贪婪正则表达式的解决方案,因为搜索模式如下所示:^.+?,|,IN:.+?\-|,OUT:.+?-|State.+?[$,]

4

2 回答 2

1

假设您有grep -P,这里有一个简单的 Awk 后处理器,用于将输出重新排列为所需的格式。

grep -Pno '^.+?,|,IN:.+?\-|,OUT:.+?-|State.+?[$,]' - /dev/null <file |
awk 'BEGIN { re="^\\(standard input\\):[1-9][0-9]*:" }
    $0 ~ re { sep="\n"; sub(re, "") }
    { if(NR>1) printf "%s", sep; printf "%s", $0; sep=" " }
    END { if(sep) printf "\n" }'

如果grep结果可能意外输出一个看起来像(standard input):1:实际匹配的前缀,这将不起作用。

这是来自 BSD grep;如果您的本地grep为标准输入输出不同格式的文件名前缀(或者如果您需要重构以读取许多命名文件而不是标准输入),则需要相应地调整 Awk 正则表达式。

于 2020-01-29T09:35:25.180 回答
0

您可以使用

 while IFS= read -r line; do
   echo $(grep -oP 'aaa|xx|zz' <<< "$line");
 done < file

那是,

  1. 逐行读取输入文件
  2. grep使用每行的命令获取匹配项
  3. shell 将用空格转换换行符,因为$(...)没有用双引号括起来。

如果您在要保留的匹配项中有特定的空格,请考虑使用

while IFS= read -r line; do 
  echo "$(grep -oP 'aaa|xx|zz' <<< "$line" | awk '{ printf "%s", $0" "}')"; 
done < file

这样,您将以空格分隔的方式获得每行匹配。awk您可以在命令中使用任何自定义分隔符(在 之后$0)。

于 2020-01-29T09:45:18.433 回答