我正在尝试搜索一个具有前瞻性的regex,它在pcregrep或grep 中不起作用
我想搜索部分的位
- ,其可以跨越多条线
- 其在一行的开头以PQXY开始,并且
- 以线路末端的OFEJ结束,以及
- 不包含介于之间的PQXY或OFEJ
Generall我在崇高的文本中使用以下内容查找并运行良好
(?s)(^PQXY(?:(?!PQXY|OFEJ).)*OFEJn)
现在我想找到这样的发生次数,所以我尝试使用grep或pcergrep,两者都不起作用。
pcregrep -c "(?s)(^PQXY(?:(?!PQXY|OFEJ).)*OFEJn)" file.txt
zsh: event not found: PQXY|OFEJ).)
和grep
$ grep -c -zoP "(?s)(^PQXY(?:(?!PQXY|OFEJTRANS).)*OFEJTRANSn)" CB_raw_testing_21_feb_CORRECTIONS_0002.txt
zsh: event not found: PQXY|OFEJTRANS).)
我该怎么做这个
基于@paxdiablo和@anubha的回答
主要错误是@paxdiablo 处理的单引号
$ pcregrep -c -M '(^PQXY(?:(?!PQXY|OFEJ).)*OFEJn)' file.txt
0
正则表达式的解决方案是基于@anubha添加(?s(。当然n
也可以代替(R|z)
$ pcregrep -c -M '(?s)(^PQXY(?:(?!PQXY|OFEJ).)*OFEJn)' file.txt
11726
zsh: event not found: PQXY|OFEJ).)
由于这是zsh
引发错误,所以它几乎是当然,因为它试图处理双引号中的内容。为了避免这种情况,您应该使用单个引号,例如:
pcregrep -c '(?s)(^PQXY(?:(?!PQXY|OFEJ).)*OFEJn)' file.txt
我没有安装pcregrep
,但这里有一份文字记录,显示了echo
:的问题
pax> echo "(?s)(^PQXY(?:(?!PQXY|OFEJ).)*OFEJ)"
zsh: event not found: PQXY|OFEJ).)
pax> echo '(?s)(^PQXY(?:(?OFEJ)'
(?s)(^PQXY(?:(?OFEJ)
在解决问题而不是使用特定的工具方面,在这种情况下,我实际上会选择awk
(a(。你可以做一些类似的事情:
awk '/^PQXY/ { s = $0; c = 1; next}
/OFEJ$/ { if (c == 1) { print s""ORS""$0; c = 0 }; next }
/OFEJ|PQXY/ { c = 0; next }
c == 1 { s = s""ORS""$0 }' inputFile
这是通过使用字符串和标志来控制收集的行和状态来实现的,最初它们是空字符串和零。
然后,对于每一行:
- 如果它以PQXY开始,则存储该行并设置采集标志,然后转到下一个输入行
- 否则,若它以
OFEJ
结束并且您正在收集,则输出收集的部分并停止收集,然后转到下一个输入行 - 否则,若其中包含任意一个字符串,则停止收集,移动到下一个输入行
- 否则,若正在收集,请附加当前行并(隐式(移动到下一个输入行
我已经用一些有限的测试数据进行了测试,它似乎可以正常工作。这是我用于测试的bash
脚本(b(,您可以根据需要添加任意多的测试用例,这样可以解决您的问题。
for i in
"PQXY 1nabcn2 OFEJn"
"PQXY 1nabcn2 OFEJxn"
"PQXY 1nabcn PQXY n2 OFEJn"
"PQXY 1nabcn OFEJ n2 OFEJn"
"PQXY 1nabcndefnPQXY 2n2 OFEJn"
; do
echo "$i:"
printf "$i" | awk '
/^PQXY/ { s = $0; c = 1; next}
/OFEJ$/ { if (c == 1) { print s""ORS""$0; c = 0 }; next }
/OFEJ|PQXY/ { c = 0; next }
c == 1 { s = s""ORS""$0 }' | sed 's/^/ /
'
done
这是输出,所以你可以看到它的作用:
PQXY 1nabcn2 OFEJn:
PQXY 1
abc
2 OFEJ
PQXY 1nabcn2 OFEJxn:
PQXY 1nabcn PQXY n2 OFEJn:
PQXY 1nabcn OFEJ n2 OFEJn:
PQXY 1nabcndefnPQXY 2n2 OFEJn:
PQXY 2
2 OFEJ
(a(根据我的经验,如果你用grep
风格的正则表达式尝试了三件事都没有成功,那么转移到更高级的工具通常会更快:-(
(b(是的,我知道它是用bash
而不是zsh
写的,但这是因为:
- 这是一个测试程序,向您展示
awk
的工作原理,因此使用的语言无关紧要;以及 - 我对
bash
比zsh
:-舒服得多。(
使用gnu grep
:
grep -ozP '(?ms)^PQXY(?:(?!PQXY|OFEJ).)*OFEJ(R|z)' file
必须使用
-z
选项将输入和输出数据视为行序列,每个行以零字节结束。请确保对您的模式使用单引号,这样shell的历史记录模块就不会试图处理
!
。- 添加了
(?m)
(MULTILINE(修饰符,允许在正则表达式中为每行使用^
和$
- 使用
(R|z)
允许结束模式在文件末尾不带换行符的情况下结束。R
匹配换行符的任何ind,包括unicode字符,z
匹配输入的末尾
工作演示
pcregrep
中的等效解
pcregrep -M '(?s)^PQXY(?:(?!PQXY|OFEJ).)*OFEJ(R|z)' file
CCD_ 26启用CCD_ 27中的多行光学。