extrai o número da linha e o padrão no arquivo ao mesmo tempo

0

Eu li um monte de arquivos de texto para extrair alguns padrões. Eu preciso do número da linha também, mas o número da linha deve ser removido antes do grep final (mas pode ser salvo para processamento adicional, talvez usando variáveis).

Vou explicar meu procedimento dividindo o comando (oneliner longo) para melhor compreensão:

  1. leia o arquivo com cat , faça alguma limpeza (remova caracteres estranhos e feeds de linha usando sed e tr ) e outros. Aqui apenas um exemplo de muitas tarefas de limpeza encanada:

     cat file | sed 's/,/ /g' | sed '/^$/d'
    
  2. adicione o número da linha e a tabulação com o comando nl & mais processamento e limpeza

     nl -nrz -w4 -s$'\t' | tr '\n\r' ' '
    
  3. extraia o padrão final desejado para o arquivo CSV

     grep -Eio '.{0,0}account number.{0,15}' >> account_list.csv
    

A questão é que eu preciso do número da linha do passo 2 para o mesmo CSV (outra coluna, não importa a ordem) usando o MESMO COMANDO DE LINHA (não há tempo ou loop permitido), mas nenhum sucesso até agora.

[EDITADO para melhor compreensão] Leve em conta que o número da linha que eu preciso é o original antes da limpeza do arquivo. Este processo de limpeza, por vezes, exclui alguns parágrafos. Imagine um arquivo com mil linhas, depois do processamento recebi cem. A nova numeração de linhas está errada. [end edit]

Amostra imputada após algum processamento:

0123 the first account number 2345356432 must be used
0345 take it just for billing purposes, not any other.
0657 Meanwhile the second account number 8623525534
0987 user is blocked until the issue is solved with

A saída desejada seria:

 2345356432; 0123
 8623525534; 0657

ou

0123; 2345356432
0657; 8623525534

qualquer sugestão seria muito apreciada

    
por jomaweb 18.08.2016 / 11:04

4 respostas

3

Usando awk no arquivo de entrada original, antes da limpeza:

awk '/account number [[:digit:]]+/ { match($0, "account number ([[:digit:]]+)", a); print NR ";" substr($0, a[1, "start"], a[1, "length"]); }' input

Isso extrai o número da conta e imprime o número da linha no início da linha:

1;2345356432
3;8623525534

Se você quiser extrair o número pré-processado do arquivo limpo:

awk '/account number [[:digit:]]+/ { match($0, "account number ([[:digit:]]+)", a); print $1 ";" substr($0, a[1, "start"], a[1, "length"]); }' input

Dividindo isso um pouco:

  • /account number [[:digit:]]+/ garante que processamos apenas linhas que correspondam a "número da conta" seguido por um número;
  • match($0, "account number ([[:digit:]]+)", a) procura o padrão novamente e armazena as posições e comprimentos dos grupos correspondentes ( ([[:digit:]]+) , o número) na matriz a ;
  • print NR ";" substr($0, a[1, "start"], a[1, "length"]) imprime o número do registro ( ie o número da linha; use FNR se você quiser processar vários arquivos), seguido por ; , seguido pela substring correspondente ao primeiro grupo: a[1, "start"] fornece seu índice inicial, a[1, "length"] seu comprimento (isso foi preenchido por match ).

Tudo isso pressupõe que haja no máximo um número de conta por linha.

A segunda variante imprime $1 em vez de NR , ou seja, o primeiro campo no arquivo, que é o número da linha pré-processada.

    
por 18.08.2016 / 11:07
0

Se a sua versão do grep suporta expressões regulares Perl, você pode usar look-behind:

grep -Pnio "(?<=account number.)([0-9]{0,15})" text
    
por 18.08.2016 / 11:39
0

Considerando sua entrada e saída, um script awk parece muito mais simples:

gawk '/account number/ {
    nr=gensub(/.*account\s*number\s*([0-9]+).*/, "\1", "g")
    print FNR "; " nr
}'

É claro que você pode precisar adaptar a extração do número da conta e o formato de saída para seus gostos. Mas você entendeu a ideia. (Requer o GNU awk devido ao uso da função gensub .)

    
por 18.08.2016 / 11:42
0

Eu ficaria tentado a usar o Perl para isso, algo assim deveria funcionar:

perl -ne 'print "$1; $2\n" if /^(\d+).*account number (\d+)/' input

Nas linhas que começam com alguns dígitos ( ^\d+ ) e contêm a string "account number" seguida por alguns dígitos, imprima o primeiro e o segundo grupos de captura (partes entre parênteses, aqui os números). Se você quiser imprimir a ideia de Perl do número da linha, use $. em vez de $1 .

    
por 18.08.2016 / 16:33