Pula a primeira linha da saída de cada iteração do XARGS

1
cut -d, -f2 parsed_repayment.csv | uniq -d | xargs -n1  -I{} grep {} parsed_repayment.csv | wc -l

Eu basicamente quero pular a primeira correspondência para cada comando grep e gravá-los em um arquivo, mas xargs combina toda a saída. Existe alguma maneira prática de conseguir isso?

Por exemplo, digamos que eu tenha uma lista de palavras 'dog', 'cat', 'horse'. Eu quero procurar todas as três palavras em um arquivo usando grep. Agora, suponha que o arquivo contenha 2 linhas correspondentes para cada palavra -

dog l1
dog l2
cat l1
cat l2
horse l1
horse l2

A saída que espero é -

dog l2
cat l2
horse l2

Para cada palavra pesquisada, quero que ela pule a primeira correspondência. Além disso, cada palavra pode ter um número diferente de correspondências.

Eu tentei gravar a saída depois do grep em um arquivo temporário e depois cortar a primeira linha usando o comando tail, mas como xargs está passando correspondências para todas as palavras dadas juntas, não consigo pular a primeira correspondência para palavras individuais. / p>     

por krrish 27.04.2018 / 13:21

4 respostas

1

Soa como um problema XY e você realmente quer:

awk -F, '$2 == prev; {prev = $2}' < parsed_repayment.csv

Ou seja, relate as linhas em que o segundo campo é o mesmo que o segundo campo da linha anterior.

Para a resposta ao que você perguntou, ao contrário do que você realmente queria, seria:

cut -d, -f2 parsed_repayment.csv |
  uniq -d |
  xargs sh -c '
    for i do
      grep -e "$i" parsed_repayment.csv | tail -n +2
    done' sh

Mas isso tem algumas ressalvas:

  • xargs espera um formato de entrada muito específico. Se os valores da segunda coluna contiverem espaços em branco ou aspas simples ou duplicar aspas ou barras invertidas, isso não funcionará corretamente.
  • grep entende que $i como expressão regular . E mesmo se você usar -F ou se essas cadeias não contiverem operadores de expressões regulares (como . , $ ...), grep procuraria essas cadeias em qualquer lugar da linha, não apenas em o segundo campo, e muito menos exatamente como o segundo campo.
por 27.04.2018 / 13:48
0

Você pode usar sed -e 1d como um canal em vez de grep dentro de xargs da seguinte forma:

xargs -n1 -I{} bash -c 'grep {} apt-installed |sed -e 1d'

Então, finalmente:

cut -d, -f2 parsed_repayment.csv | uniq -d | xargs -n1 -I{} bash -c 'grep {} apt-installed |sed -e 1d' | wc -l

    
por 27.04.2018 / 13:46
0

O texto a seguir escreve a primeira linha de entrada para o arquivo foo e reflete o restante:

read line ; echo "$line" >> foo ; while read line ; do echo "$line" ; done 

Teste, por exemplo assim:

seq 0 9 | ( read line ; echo "$line" > foo ; while read line ; do echo "$line" ; done ) 
cat foo

Agora, em vez de executar grep diretamente em xargs , execute um canal que coloque a saída de grep através do fragmento acima. Isso resolve o problema de xargs concatenar todas as saídas.

A coisa toda é longa o suficiente para considerar colocar o fragmento em um script de shells, esp. se você quiser controlar o nome do arquivo.

Editar

Isso pressupõe que você queira escrever a entrada que você pulou para um arquivo e o resto para stdout, mas talvez eu tenha entendido errado.

    
por 27.04.2018 / 13:46
0

Com o GNU Parallel, é assim:

cut -d, -f2 parsed_repayment.csv | uniq -d |
  parallel 'grep {} parsed_repayment.csv | tail -n +2'
    
por 04.05.2018 / 08:37

Tags