我需要从 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 都打印在|| :var
s 之前)。
或者,如果您只想要: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
和,您可以标准地执行以下操作::bar
anything :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