我想确保文件遵循以下模式:
... ... ... 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