Detectar repetição de padrões em um arquivo

2

Eu quero ter certeza de que um arquivo segue o seguinte padrão:

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

O arquivo é extremamente longo, ou seja, quero ter certeza da seguinte regra, em sed terms:

Toda vez que ([a-z] *) _ KO é correspondido, existe outro campo na mesma linha cujo valor é \ 1.

Eu aposto que sou claro o suficiente.

Estou no Solaris 10, usando o ksh.

Exemplo:

intput

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

saída

valid

entrada

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

saída

invalid line 3 

ou

unmatched pattern fubar_KO
    
por rahmu 07.05.2012 / 12:16

2 respostas

4

Isso mostrará os números das linhas inválidas:

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

Mas não lida com vários "_KO" em uma linha.

Isso deve ser mais confiável e portátil:

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

Isso é mais complicado, mais eficiente e suporta vários padrões, mas dependendo da classificação, as configurações de localidade podem afetar seu sucesso:

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

Basicamente o mesmo que a solução awk acima, mas parece menos detalhado em 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
    
por 07.05.2012 / 12:29
3

Algum enigma críptico:

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

/(\w+)_KO\b/ localiza a palavra "_KO" e captura a parte não-KO na variável $1 e !/\b$1(?!_KO)\b/ é verdadeira se NÃO houver palavra "autônoma" sem _KO ( \b é um limite de palavra )
Se essas duas condições forem verdadeiras, imprima a mensagem de erro.

Para determinar se o arquivo é "válido",

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

ou

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
    
por 07.05.2012 / 15:07