grep até o final da citação

2

Eu tenho um arquivo de texto de exemplo (test_long_sentence.txt) abaixo e quero usar todas as linhas que contêm test1, excluindo dados indesejados.

Como eu faço o grep dos dados antes do fechamento da cotação?

test_long_sentence.txt

This is some unwanted data blah blah blah

20  /test1/catergory="Food"
20  /test1/target="Adults, \"Goblins\", Elderly,
Babies, \"Witch\",
Faries"
20  /test1/type="Western"

This is some unwanted data blah blah blah

20  /test1/theme="Halloween"

Comando:

grep "test1" test_long_sentence.txt

Saída real:

20  /test1/catergory="food"
20  /test1/target="Adults, \"Goblins\", Elderly,
20  /test1/type="Western"
20  /test1/theme="Halloween"

Resultado esperado:

20  /test1/catergory="food"
20  /test1/target="Adults, \"Goblins\", Elderly,
Babies, \"Witch\",
Faries"
20  /test1/type="Western"
20  /test1/theme="Halloween"

Ps: Eu não tenho controle na edição do test_long_sentence.txt. Então, por favor, não me peça para editá-lo em uma única linha.

    
por Jojoleo 12.02.2018 / 04:27

3 respostas

0

Usando o awk

$ awk '/test1/{line=$0; while (!(line ~ /[^\]".*[^\]"/)) {getline; line=line "\n" $0}; print line}' sentence.txt 
20  /test1/catergory="Food"
20  /test1/target="Adults, \"Goblins\", Elderly,
Babies, \"Witch\",
Faries"
20  /test1/type="Western"
20  /test1/theme="Halloween"

/test1/ é uma condição. Se a linha atual contiver uma correspondência para o regex test1 , os comandos nas chaves serão executados. Esses comandos são:

  • line=$0

    O conteúdo da linha atual é salvo na linha da variável.

  • while (!(line ~ !/[^\]".*[^\]"/)) {getline; line=line "\n" $0}

    Se o conteúdo atual de line não contiver duas citações sem escape, obtenha a próxima linha, getline e anexe-a a line via line=line "\n" $0

  • print line

    Agora que a variável line contém duas citações sem escape, nós a imprimimos.

Para aqueles que preferem seus comandos espalhados por várias linhas, o mesmo comando acima pode ser escrito como:

awk '
    /test1/{
        line=$0
        while (!(line ~ /[^\]".*[^\]"/)) {
            getline
            line=line "\n" $0
        }
        print line
    }' sentence.txt 

Usando sed

$ sed -n '/test1/{:a; /[^\]".*[^\]"/{p;b}; N; ba}' sentence.txt 
20  /test1/catergory="Food"
20  /test1/target="Adults, \"Goblins\", Elderly,
Babies, \"Witch\",
Faries"
20  /test1/type="Western"
20  /test1/theme="Halloween"

Como funciona:

  • -n

    Isso diz ao sed para não imprimir nada a menos que explicitamente o solicitemos.

  • /test1/{...}

    Para qualquer linha contendo test1 , executamos os comandos em chaves, que são:

    • :a

      Isso define um rótulo a .

    • /[^\]".*[^\]"/{p;b}

      Se o espaço padrão atualmente contém duaspas sem escape, nós imprimimos o espaço padrão, p , e então pulamos o resto das instruções e a ramificação, b , para recomeçar na próxima linha.

    • N

      Se chegarmos aqui, isso significa que a corrente não tem duas citações sem escape. Nós lemos na próxima linha no espaço padrão.

    • ba

      Retornamos para o rótulo a e repetimos os comandos que seguem esse rótulo.

por 12.02.2018 / 05:11
0

Isso funcionará com awk em vez de grep para esse arquivo específico:

awk 'NR==3,NR==7;NR==11' test_long_sentence.txt

Para ajudar com isso no futuro, você pode executar cat -n no arquivo para ver as linhas que deseja incluir e excluir.

    
por 12.02.2018 / 05:03
0

Aqui está um script perl simples para se juntar às linhas contínuas da sua entrada. Assume:

  • as linhas contínuas devem ser unidas com um único caractere de espaço.

  • uma "linha" começa em qualquer linha de entrada que comece com um número e um espaço e continua até:

    • um espaço em branco como
    • outra linha que começa com um número e um espaço
  • linhas em branco e todas as linhas entre linhas em branco devem ser ignoradas (isto é, descartadas).

Isso pode não ser uma correspondência perfeita para o arquivo de entrada real, mas corresponde à entrada de amostra fornecida na sua pergunta. Modifique o código para se adequar à sua entrada, conforme necessário.

#!/usr/bin/perl

my $skip=1;  # start with skip = true.
my $line='';

while(<>) {
  chomp;

  if (m/^\d+\s+/) { # / this comment is only here to fix SE\'s syntax highlighting
    $skip=0;
    print $line,"\n" if ($line);
    $line = $_;

 } elsif (m/^\s*$/) {
    if ($line ne '') { print $line, "\n"; $line = ''};
    $skip = 1 - $skip;

  } elsif (! $skip) {
    $line .= " $_";
 };
};

salve como, por exemplo, ./join-lines.pl , torne executável com chmod +x ./join-lines.pl e execute como:

$ ./join-lines.pl test_long_sentence.txt 
20  /test1/catergory="Food"
20  /test1/target="Adults, \"Goblins\", Elderly, Babies, \"Witch\", Faries"
20  /test1/type="Western"
20  /test1/theme="Halloween"

Isso pode ser alimentado em grep ou outras ferramentas, conforme necessário.

Observe que, com a entrada de amostra atual, a saída de ./join-lines.pl test_long_sentence.txt | grep test1 é (além da possível colorização de correspondências por grep ) idêntica à saída acima porque todas as linhas de amostra contêm "test1". Você pode mais útil grep para outras correspondências, por exemplo:

$ ./join-lines.pl test_long_sentence.txt | grep Witch
20  /test1/target="Adults, \"Goblins\", Elderly, Babies, \"Witch\", Faries"

Se você precisar reproduzir exatamente a mesma entrada (mas sem as linhas em branco e indesejadas), em vez de unir as linhas com um espaço, use um caractere (por exemplo, uma TAB) ou uma string mais longa (por exemplo, " ===NL=== " ) que você está absolutamente certo nunca aparecerá na entrada. por exemplo,

  } elsif (! $skip) {
    $line .= "\t$_";
 };

ou

  } elsif (! $skip) {
    $line .= " ===NL=== $_ ";
 };

A string de união pode ser convertida de volta para uma nova linha com, por exemplo, sed (usando um caractere de tabulação como o caractere de união):

$ ./join-lines.pl test_long_sentence.txt  | grep Witch | sed -e 's/\t/\n/g'
20  /test1/target="Adults, \"Goblins\", Elderly,
Babies, \"Witch\",
Faries"

Outro exemplo, usando uma string mais longa para unir as linhas:

./join-lines.pl test_long_sentence.txt  | grep Witch | sed -e 's/ ===NL=== /\n/g'
    
por 12.02.2018 / 05:21