Como incrementar o contador de linhas para substituições de início de linha por AWK /…?

9

Pensei primeiro no SED ( sed "s/^/COUNTER \&/" /tmp/1.tex), mas ele foi projetado para uma única linha e não posso incrementar o contador por si só, pensando assim agora awkporque tenho ótimas experiências gawkem abordagens integradas. Dados

What & South Dragon & North Dragon    & 5 \\ \hline
What & South Dragon & North Dragon    & 5 \\ \hline
What & South Dragon & North Dragon    & 5 \\ \hline

Saída esperada

1 & What & South Dragon & North Dragon    & 5 \\ \hline
2 & What & South Dragon & North Dragon    & 5 \\ \hline
3 & What & South Dragon & North Dragon    & 5 \\ \hline

SO: Debian 8.5

Léo Léopold Hertz 준영
fonte

Respostas:

11

nl é um utilitário para numerar as linhas de um arquivo.

nl /path/to/file

No seu caso específico:

$ nl  -s ' & ' input.txt                                                                                                 
     1 & What & South Dragon & North Dragon    & 5 \\ \hline
     2 & What & South Dragon & North Dragon    & 5 \\ \hline
     3 & What & South Dragon & North Dragon    & 5 \\ \hline
DopeGhoti
fonte
Como você pode combinar isso com o contador e o e comercial? - - Funciona para o contador, mas não tenho certeza se também para o último.
Léo Léopold Hertz #
3
nl -s ' &' /path/to/file. -sespecifica o que separa os números do corpo do arquivo de entrada.
DopeGhoti
1
nldifere cat -ne a awksolução na medida em que não Número linhas vazias por padrão
Iruvar
10

Isso alcança o que você procura. (como faz awk '$0=NR" & "$0' filename, mas isso é um pouco enigmático)

awk '{print NR,"&",$0}' filename
1 & What & South Dragon & North Dragon    & 5 \\ \hline
2 & What & South Dragon & North Dragon    & 5 \\ \hline
3 & What & South Dragon & North Dragon    & 5 \\ \hline

Ou, se sedpreferível, isso dá o mesmo resultado.

sed = filename | sed 'N;s/\n/ \& /'

perl abordagens.

perl -pe '$_="$. & $_"' filename
perl -pe 's/^/$. & /' filename
Steve
fonte
Como você encontrou essa sintaxe sed = filename | ...? - - Eu não sabia que você pode usar sed com o equalsímbolo. - - Sua seddeclaração pode funcionar em ambientes dinâmicos? Alguma fraqueza?
Léo Léopold Hertz #
1
@ LéoLéopoldHertz 준영 Olhei na página de manual, o =operador está na seção "Comandos de endereço zero ou um".
Sergiy Kolodyazhnyy
Sim, = Print the current line number. Portanto, o recurso é realmente embutido no sed. Agradável!
Léo Léopold Hertz 준영 29/12
3

Python pode ser uma boa ferramenta alternativa para isso:

$ python -c "import sys;lines=[str(i)+' & '+l for i,l in enumerate(sys.stdin,1)]; print ''.join(lines)" < input.txt      
1 & What & South Dragon & North Dragon    & 5 \\ \hline
2 & What & South Dragon & North Dragon    & 5 \\ \hline
3 & What & South Dragon & North Dragon    & 5 \\ \hline

A maneira como isso funciona é que redirecionamos o texto para o stdin do python e lemos as linhas a partir daí. enumerate()é a função que fornece a contagem de linhas, sys.stdinespecificada como entrada e 1é o índice inicial. O resto é simples - criamos uma lista de novas strings lançando o índice como string unida à ' & 'string e à própria linha. Finalmente, tudo isso é remontado da lista em um teste pela ''.join()função.

Como alternativa, aqui está uma versão de várias linhas para um arquivo de script ou simplesmente para facilitar a leitura:

#!/usr/bin/env python
import sys

for index,line in enumerate(sys.stdin,1):
    print str(index) + ' & ' + line.strip()

Funciona da mesma forma:

$ ./line_counter.py  < input.txt                                                                                         
1 & What & South Dragon & North Dragon    & 5 \\ \hline
2 & What & South Dragon & North Dragon    & 5 \\ \hline
3 & What & South Dragon & North Dragon    & 5 \\ \hline

Mas se você preferir fazê-lo no bash, isso também pode ser feito:

$ counter=1; while read line ; do printf "%s & %s\n" "$counter" "$line" ; counter=$(($counter+1)) ; done < input.txt
1 & What & South Dragon & North Dragon    & 5 \ hline
2 & What & South Dragon & North Dragon    & 5 \ hline
3 & What & South Dragon & North Dragon    & 5 \ hline
Sergiy Kolodyazhnyy
fonte
1
@ LéoLéopoldHertz 준영 Bem, se eu fizesse isso sem enumerar, precisaria de uma variável que rastreie o número de linhas, e preciso iniciar essa variável e aumentar cada vez. O uso enumerate()economiza três linhas de código. É útil ao lidar com outras coisas, como processar itens em listas. Veja docs.python.org/2/library/functions.html#enumerate
Sergiy Kolodyazhnyy
@ LéoLéopoldHertz 준영 Se você entende usar o contador como eu no bashexemplo, sinta-se à vontade para usá-lo :) Acabei de descobrir que a experiência enumerate()é mais elegante, mas essa é apenas a minha opinião. Por todos os meios, use outro método se você achar que é mais claro #
Sergiy Kolodyazhnyy 28/12
OK, enumerateé mais claro que a instanciação variável. A expressão lambda pode economizar algum espaço?
Léo Léopold Hertz # 29/16
@ LéoLéopoldHertz could Poderia economizar espaço em um script longo, mas, neste caso, não vejo como isso poderia ajudar.
Sergiy Kolodyazhnyy
2

Essa também é uma opção usada cat -ncom numeração automática:

while read num line;do echo $num "&" $line;done <<<$(cat -n a.txt)
George Vasiliou
fonte