我有一个如下文件
FHEAD
THEAD
TCUST
TITEM
TTEND
TTAIL
THEAD
TCUST
TCUST
TITEM
TITEM
TTEND
TTAIL
THEAD
TCUST
TITEM
TTEND
TTAIL
THEAD
TCUST
TCUST
TITEM
TTEND
TTAIL
我需要计算 THEAD 和 TTAIL 之间出现多次的 ONLY TCUST 记录的出现次数,并打印该文件名和行。
将有多个文件,因此我还需要打印文件名。
预期结果是
THEAD TCUST TCUST TITEM TITEM TTEND TTAIL THEAD TCUST TCUST TITEM TTEND TTAIL 文件名
答案1
$ awk '
/THEAD/{f=1; c=0; a = $0; next}
f{a = a ORS $0; if(/TCUST/) c++}
/TTAIL/{f=0; if(c > 1){print a; m=1} }
ENDFILE{if(m) print FILENAME; m=0}
' ip.txt
THEAD
TCUST
TCUST
TITEM
TITEM
TTEND
TTAIL
THEAD
TCUST
TCUST
TITEM
TTEND
TTAIL
ip.txt
/THEAD/{f=1; c=0; a = $0; next}
启动模式,设置标志并初始化计数器。保存当前行以供以后打印f{a = a ORS $0; if(/TCUST/) c++}
设置标志后,将输入行累积到a
变量中,如果行匹配则增加计数器TCUST
/TTAIL/{f=0; if(c > 1){print a; m=1} }
结束模式,清晰的标志。a
如果 counter 大于 则打印内容1
,同时设置m
至少找到一个匹配项的变量ENDFILE{if(m) print FILENAME; m=0}
处理完文件的所有行后,打印输入文件名(如果m
已设置)并在处理下一个文件之前清除(感谢@Costas 指出多个文件要求)
笔记: ENDFILE
是GNU awk
具体的,我不知道如何处理它没有ENDFILE
感谢 @Costas 提供不依赖于 GNU 特定的解决方案ENDFILE
:
$ awk '
FNR==1{if(m) print fname; m=0; fname=FILENAME}
/THEAD/{f=1; c=0; a = $0; next}
f{a = a ORS $0; if(/TCUST/) c++}
/TTAIL/{f=0; if(c > 1){print a; m=1} }
END{if(m) print fname}
' *.txt
答案2
通过 GNU sed 可以通过以下方式完成任务
sed -sn '
/THEAD/{:1;N;/TTAIL/! b1} #collect lines from `THEAD' to `TTAIL'
/TCUST.*TCUST/{p;h} #print if there are two TCUST and set hold
${x;//F} #check hold and output if two TCUST was in it
' file1 file2 …