Jak zwiększyć licznik linii dla zamiany początku linii na AWK /…?

9

Najpierw pomyślałem o SED ( sed "s/^/COUNTER \&/" /tmp/1.tex), ale jest on zaprojektowany dla pojedynczej linii i nie mogę zwiększyć licznika przez sed tak myśląc teraz, awkponieważ mam świetne doświadczenia ze gawkzintegrowanymi podejściami. Dane

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

Oczekiwany wynik

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

System operacyjny: Debian 8.5

Léo Léopold Hertz 준영
źródło

Odpowiedzi:

11

nl to narzędzie do numerowania linii pliku.

nl /path/to/file

W twoim konkretnym przypadku:

$ 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
źródło
Jak można to połączyć z licznikiem i aplikacją? - - Działa dla licznika, ale nie jestem pewien, czy również dla tego ostatniego.
Léo Léopold Hertz -
3
nl -s ' &' /path/to/file. -sokreśla, co oddziela liczby od treści pliku wejściowego.
DopeGhoti
1
nlróżni się od cat -ni awkrozwiązanie w tym, że nie liczba pustych linii domyślnie
Iruvar
10

To osiąga to, czego szukasz. (jak robi awk '$0=NR" & "$0' filename, ale to trochę tajemnicze)

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

Lub jeśli jest to sedpreferowane, daje to ten sam rezultat.

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

perl podejścia.

perl -pe '$_="$. & $_"' filename
perl -pe 's/^/$. & /' filename
Steve
źródło
Jak znalazłeś tę składnię sed = filename | ...? - - Nie wiedziałem, że możesz używać sed z equalsymbolem. - - Czy twoje sedoświadczenie może działać w dynamicznych środowiskach? Jakieś słabości?
Léo Léopold Hertz -
1
@ LéoLéopoldHertz looked Zajrzałem do strony podręcznika użytkownika, =operator znajduje się w sekcji „Polecenia zera lub jeden adres”.
Sergiy Kolodyazhnyy
Tak = Print the current line number. Tak więc funkcja jest faktycznie wbudowana w sed. Miły!
Léo Léopold Hertz -
3

Python może być dobrym alternatywnym narzędziem do tego:

$ 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

Działa to tak, że przekierowujemy tekst do standardowego interfejsu Pythona i odczytujemy stamtąd wiersze. enumerate()funkcja podaje liczbę wierszy, sys.stdinpodana jako dane wejściowe i 1jest indeksem początkowym. Reszta jest prosta - tworzymy listę nowych ciągów, rzutując indeks jako ciąg połączony razem z ' & 'ciągiem i samą linią. Wreszcie, wszystko to jest ponownie składane z listy w jeden test przez ''.join()funkcję.

Alternatywnie, oto wieloliniowa wersja pliku skryptu lub po prostu dla czytelności:

#!/usr/bin/env python
import sys

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

Działa tak samo:

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

Ale jeśli wolisz robić to w bashu, możesz to również zrobić:

$ 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
źródło
1
@ LéoLéopoldHertz 준영 Cóż, gdybym zrobił to bez wyliczenia, potrzebowałbym zmiennej, która śledzi liczbę linii, i muszę ją inicjować i za każdym razem zwiększać. Używanie enumerate()oszczędza jak 3 linie kodu. Jest to przydatne, gdy mamy do czynienia z innymi rzeczami, takimi jak przetwarzanie pozycji na listach. Zobacz docs.python.org/2/library/functions.html#enumerate
Sergiy Kolodyazhnyy
@ LéoLéopoldHertz 준영 jeśli rozumiesz używanie licznika tak jak ja na bashprzykład, to skorzystaj z niego :) Właśnie z doświadczenia zauważyłem, enumerate()że jest bardziej elegancki, ale to tylko moja opinia.
Oczywiście
OK, enumeratejest bardziej przejrzysty niż tworzenie instancji zmiennej. Czy wyrażenie lambda może zaoszczędzić trochę miejsca?
Léo Léopold Hertz 준영
@ LéoLéopoldHertz 준영 To może zaoszczędzić miejsce w długim skrypcie, ale w tym przypadku po prostu nie widzę, jak to może pomóc.
Sergiy Kolodyazhnyy
2

Jest to również opcja korzystająca cat -nz automatycznego numerowania:

while read num line;do echo $num "&" $line;done <<<$(cat -n a.txt)
George Vasiliou
źródło