¿Cómo incrementar el contador de línea para los reemplazos de inicio de línea por AWK / ...?

9

Primero pensé en SED ( sed "s/^/COUNTER \&/" /tmp/1.tex), pero está diseñado para una sola línea, y no puedo incrementar el contador por sí mismo, así que ahora pienso awkporque tengo grandes experiencias con gawkenfoques integrados. Datos

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

Rendimiento esperado

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 준영
fuente

Respuestas:

11

nl es una utilidad para numerar las líneas de un archivo.

nl /path/to/file

En tu 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
fuente
¿Cómo puedes combinar esto con el contador de preappending y el ampersand? - - Funciona para el mostrador, pero no estoy seguro si también para este último.
Léo Léopold Hertz 준영
3
nl -s ' &' /path/to/file. -sespecifica qué separa los números del cuerpo del archivo de entrada.
DopeGhoti
1
nldifiere de cat -ny la awksolución en que no
numera
10

Esto logra lo que buscas. (como lo hace awk '$0=NR" & "$0' filename, pero eso es un poco críptico)

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

O si es sedpreferible, esto da el mismo resultado.

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

perl enfoques.

perl -pe '$_="$. & $_"' filename
perl -pe 's/^/$. & /' filename
Steve
fuente
¿Cómo encontraste esta sintaxis sed = filename | ...? - - No sabía que puedes usar sed con el equalsímbolo. - - ¿Puede su seddeclaración funcionar en entornos dinámicos? ¿Alguna debilidad?
Léo Léopold Hertz 준영
1
@ LéoLéopoldHertz 준영 Busqué en la página de manual, el =operador está en la sección "Comandos de cero o una dirección".
Sergiy Kolodyazhnyy
Sí, = Print the current line number. Por lo tanto, la función está incorporada en sed. ¡Agradable!
Léo Léopold Hertz 준영
3

Python puede ser una buena herramienta alternativa para esto:

$ 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

La forma en que esto funciona es que redirigimos el texto al stdin de Python y leemos líneas desde allí. enumerate()La función es lo que da el recuento de líneas, sys.stdinespecificado como entrada y 1es el índice inicial. El resto es simple: hacemos una lista de nuevas cadenas al convertir el índice como una cadena unida con una ' & 'cadena y la línea misma. Finalmente, todo lo que la función vuelve a montar de la lista en una prueba ''.join().

Alternativamente, aquí hay una versión de varias líneas para un archivo de script o simplemente para facilitar la lectura:

#!/usr/bin/env python
import sys

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

Funciona igual:

$ ./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

Pero si prefieres hacerlo en bash, entonces eso también se puede hacer:

$ 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
fuente
1
@ LéoLéopoldHertz 준영 Bueno, si tuviera que hacer eso sin enumerar, necesitaría una variable que rastree el número de líneas, y necesito iniciar esa variable e incrementarla cada vez. Usando enumerate()ahorra como 3 líneas de código. Es útil cuando se trata con otras cosas, como procesar elementos en listas. Ver docs.python.org/2/library/functions.html#enumerate
Sergiy Kolodyazhnyy
@ LéoLéopoldHertz 준영 si entiendes usar el contador como lo hago yo, por bashejemplo, entonces siéntete libre de usar eso :) Por experiencia me pareció enumerate()más elegante, pero esa es solo mi opinión. Por supuesto, use otro método si cree que está más claro
Sergiy Kolodyazhnyy
OK, enumeratees más claro que la instanciación variable. ¿Puede la expresión lambda ahorrar algo de espacio?
Léo Léopold Hertz 준영
@ LéoLéopoldHertz could Podría ahorrar espacio en una secuencia de comandos larga, pero en este caso, simplemente no veo cómo eso podría ayudar.
Sergiy Kolodyazhnyy
2

Esta también es una opción que se usa cat -ncon la numeración automática:

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