grep 匹配所有出现的多个正则表达式

grep 匹配所有出现的多个正则表达式

我需要从 SQL 语句中提取作为串联一部分的所有主变量。输入示例:

select * from table where :first-var || :second-var

从中我需要提取“first-var”和“second-var”。

可以使用以下方法来匹配其中之一:

grep -o -E ':\S+\s+\|\|'

匹配 ':first-var ||'和

grep  -o -E '\|\|\s+:\S+'

匹配'|| :第二个变量'

但是,当我以交替模式组合这两个表达式时,仅返回一个结果:

grep -o -E '\|\|\s+:\S+|:\S+\s+\|\|'

将命令拆分为多种模式也仅匹配一种结果:

grep -o -E -e '\|\| :second-var' -e ':first-var \|\|'

怀疑管道符号在第一次匹配后“用完”,因为以下确实返回两​​个结果:

grep -o -E -e '\| :second-var' -e ':first-var \|'

我怎样才能获得所有比赛?请注意,串联符号不需要成为输出的一部分,我只对本例中的“first-var”和“second-var”感兴趣。

答案1

问题是,找到 后:first-var |||| :second-var剩余的文本就没有了。grep -o只能打印不重叠的部分线条。

你可以这样做:

$ perl -lne 'print for /:\S+\s+\|\|/g, /\|\|\s+:\S+/g' file
:first-var ||
|| :second-var

(所有:var ||s 都打印在|| :vars 之前)。

或者,如果您只想要:var部分,请使用grep带有 PCRE 支持的 GNU:

$ grep -Po ':\S+(?=\s+\|\|)|\|\|\s+\K:\S+' file
:first-var
:second-var

与...一样:

perl -lne 'print for /:\S+(?=\s+\|\|)|\|\|\s+\K:\S+/g'

现在,如果您想要在始终形状为 的线条中提取:foo和,您可以标准地执行以下操作::baranything :foo || :bar

s='[[:space:]]\{1,\}' S='[^[:space:]]\{1,\}'
sed -n "/\(:$S\}\)$s\{1,\}||$s\(:$S\).*/{
  s//\
\1\
\2/
  s/.*\n\(.*\n\)/\1/p
}'

答案2

perl -nE 'say "$1\n$2" if /(:\S+)\s*\|\|\s*(:\S+)/'

答案3

无需尝试构建复杂的正则表达式,只需对文件进行两次传递:

grep -o '|| *[^ ]*' file
grep -o '[^ ]* *||' file

或者,结合awk

grep -o '[^ ]* *|| *[^ ]*' file | awk -F' *\\|\\| *' '{ print $1; print $2 }'

给出示例行

select * from table where :first-var || :second-var

这会产生

:first-var
:second-var

相关内容