检测文件中的模式重复

检测文件中的模式重复

我想确保文件遵循以下模式:

... ... ... foo ... foo_KO ... ... 
... bar ... ... ... ... bar_KO ...

该文件非常长,因此,换句话说,我想确保以下规则sed

每次匹配 ([az]*)_KO 时,同一行上都会有另一个值为 \1 的字段。

我希望我足够清楚。

我使用的是 Solaris 10,使用 ksh。

例子:

输入

... ... ... foo ... foo_KO ... ... 
... bar ... ... ... ... bar_KO ...

输出

valid

输入

... ... ... foo ... foo_KO ... ... 
... bar ... ... ... ... bar_KO ...
... fubar_KO ... ... ... ... ... 

输出

invalid line 3 

或者

unmatched pattern fubar_KO

答案1

这将输出无效行的行号:

sed -n '/\([a-z]\+\).*\1_KO/b;/\([a-z]\+\)_KO.*\1/b;=' input_file

但不处理一行上的多个“_KO”。


这应该更可靠和便携:

awk '{for(i=1;i<=NF;i++)if((s=$i)~/^([a-z]+)_KO/){sub(/_KO$/,"",s);o=0;for(j=1;j<=NF;j++)if($j==s)o=1;if(!o)printf"line %d unmatched %s\n",NR,s}}' input_file

这更棘手,更高效,并且支持多种模式,但取决于排序,区域设置可能会影响其成功:

ruby -nae '$F.sort!.select!{|v|v=~/^[a-z]+(_KO)?$/};$F.each_with_index{|v,k|puts"line #{$.} unmatched #{v}"if v[/^([a-z]+)_KO$/]and$F[k-1]!=$1}' input_file

与上面的解决方案基本相同awk,但看起来不那么冗长perl

perl -nae 'for$k(grep/^[a-z]+_KO$/,@F){print"line $. unmatched $k\n"unless grep{$_ eq substr$k,0,-3}@F}' input_file

答案2

一些神秘的 Perl:

perl -ne '/(\w+)_KO\b/ && !/\b$1(?!_KO)\b/ && print "invalid line $.: missing $1\n"' filename

/(\w+)_KO\b/找到“_KO”单词并将非 KO 部分捕获到变量中,$1
!/\b$1(?!_KO)\b/如果没有不带 _KO 的“独立”单词(\b是单词边界) ,则为 true
如果这两个条件都为 true,则打印错误消息。

要确定文件是否“有效”,可以

output=$(perl -ne '/(\w+)_KO\b/ && !/\b$1(?!_KO)\b/ && print "invalid line $.: missing $!\n"' filename)
[ -z "$output" ] && echo valid

或者

perl -ne '
    BEGIN {$count = 0}
    if (/(\w+)_KO\b/ && !/\b$1(?!_KO)\b/) {print "invalid line $.: missing $!\n"; $count++}
    END {$count == 0 && print "valid\n"}
' filename

相关内容