我正在尝试从位于两行之间的大文件行中提取,每行都由某种模式标记,假设模式 1 和模式 2。我的代码 :
awk "/pattern1/{flag=1;next}/pattern2/{flag=0}flag" filename
验证一行中是否存在"pattern1",并从该行开始打印,直到找到字符串"pattern2"所在的后续行。
我想做的是将字符串"pattern1"与awk开始打印的行完全匹配,并通过验证行中是否存在"pattern2"来检测awk将停止打印的行(没有完全匹配)。所以基本上,我想对第一个模式进行精确匹配,并为第二个模式保留上述命令的匹配行为。
awk
内置了这样的功能:
$ cat data
abcd
pattern1
xyz
pattern2
abcde
$ awk '/pattern1/,/pattern2/' data
pattern1
xyz
pattern2
sed
也有:
$ sed -n '/pattern1/,/pattern2/p' data
pattern1
xyz
pattern2
编辑:为此,您必须使用某种锚点,无论是单词边界y
gawk
,还是像这样开始和结束锚点:
$ cat data
abcd
pattern1 234
pattern1
xyz
pattern2
abcde
$ awk '/^pattern1$/,/pattern2/' data
pattern1
xyz
pattern2
如果您想打印或不打印pattern1
/pattern2
行的组合,您可以使用这些:
$ awk '/^pattern1$/{flag=1} /pattern2/{flag=0}flag' data
pattern1
xyz
$ awk '/^pattern1$/{flag=1;next} /pattern2/{flag=0}flag' data
xyz
$ awk '/^pattern1$/{flag=1;next;} /pattern2/{flag=0;print}flag' data
xyz
pattern2
这是与问题中的建议一致的另一个答案:
awk 'BEGIN{flag=0} /^pattern1$/{flag=1;print;next} /pattern2/{flag=0;next} {if (flag == 1) {print}}'
第一种模式必须与整行完全匹配(使用 ^ 和 $),而第二种模式可以出现在线条内的任何位置。
编辑:此版本确实打印了出现模式1的行。 如果您不想打印它们,请将"flag=1;print;next"替换为"flag=1;next"。
如果没有示例输入/输出,这是一个猜测,但这可能是您想要的:
awk '/pattern2/{flag=0} flag; $0=="pattern1"{flag=1}' filename
可以写成更有意义的是:
awk '/end_regexp/{found=0} found; $0=="start_string"{found=1}' filename
(Nbd,但命名标志flag
与命名函数function
一样有用!
我实际上认为这可能是您真正应该使用的,但是idk:
awk 'index($0,"end_string"){found=0} found; $0=="start_string"{found=1}' filename
另请参阅 https://stackoverflow.com/a/18409469/1745001,了解使用 awk 查找文本的更多方法。
awk 'BEGIN{flag=0} /^pattern1$/{flag=1;print;next} /pattern2/{if (flag == 1) {print}; flag=0;} {if (flag == 1) {print}}' filename
这样就可以避免打印双重"图案2":
me:~$ awk 'BEGIN{flag=0} /^pattern1$/{flag=1;print;next} /pattern2/{if (flag == 1) {print}; flag=0;} {if (flag == 1) {print}}' a
pattern1
xyz
as pattern2 sd
me:~$ cat a
abcd
pattern1 23
pattern1
xyz
as pattern2 sd
abcde
pattern2