Bagaimana cara menambahkan penghitung garis untuk penggantian awal baris dengan AWK / ...?

9

Saya pertama kali berpikir tentang SED ( sed "s/^/COUNTER \&/" /tmp/1.tex) tetapi ini dirancang untuk satu baris, dan saya tidak bisa menambah counter itu sendiri dengan sed berpikir sekarang awkkarena saya memiliki pengalaman hebat gawkdalam pendekatan terintegrasi. Data

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

Output yang diharapkan

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

OS: Debian 8.5

Léo Léopold Hertz 준영
sumber

Jawaban:

11

nl adalah utilitas untuk memberi nomor pada baris-baris suatu file. Penggunaan:

nl /path/to/file

Dalam kasus spesifik Anda:

$ 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
sumber
Bagaimana Anda bisa menggabungkan ini dengan penghitung preappending dan ampersand? - - Ini bekerja untuk konter, tetapi tidak yakin apakah juga untuk yang terakhir.
Léo Léopold Hertz 준영
3
nl -s ' &' /path/to/file. -smenentukan apa yang memisahkan angka-angka dari badan file input.
DopeGhoti
1
nlberbeda dari cat -ndan awksolusi dalam hal itu tidak nomor baris kosong secara default
iruvar
10

Ini mencapai apa yang Anda kejar. (Seperti halnya awk '$0=NR" & "$0' filename, tapi itu agak samar)

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

Atau jika sedlebih disukai, ini memberikan hasil yang sama.

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

perl pendekatan.

perl -pe '$_="$. & $_"' filename
perl -pe 's/^/$. & /' filename
steve
sumber
Bagaimana Anda menemukan sintaks ini sed = filename | ...? - - Saya tidak tahu bahwa Anda dapat menggunakan sed dengan equalsimbol. - - Bisakah sedpernyataan Anda bekerja di lingkungan yang dinamis? Adakah kelemahan?
Léo Léopold Hertz 준영
1
@ LéoLéopoldHertz 준영 Saya mencari di bawah halaman manual, =operator di bawah bagian "Perintah Zero atau Alamat Satu".
Sergiy Kolodyazhnyy
Ya, = Print the current line number. Jadi fitur ini sebenarnya built-in sed. Bagus!
Léo Léopold Hertz 준영
3

Python dapat menjadi alat alternatif yang baik untuk ini:

$ 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

Cara kerjanya adalah kita mengarahkan teks ke stdin python, dan membaca baris dari sana. enumerate()fungsi adalah apa yang memberi jumlah baris, dengan sys.stdinditentukan sebagai input dan 1merupakan indeks awal. Sisanya sederhana - kita membuat daftar string baru dengan casting index ketika string digabungkan bersama dengan ' & 'string, dan garis itu sendiri. Akhirnya, semua itu disusun kembali dari daftar menjadi satu tes oleh ''.join()fungsi.

Atau, inilah versi multi-line untuk file skrip atau hanya untuk dibaca:

#!/usr/bin/env python
import sys

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

Bekerja sama saja:

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

Tetapi jika Anda lebih suka melakukannya di bash, maka itu bisa dilakukan juga:

$ 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
sumber
1
@ LéoLéopoldHertz 준영 Nah, jika saya melakukan itu tanpa menghitung, saya akan membutuhkan variabel yang melacak jumlah baris, dan saya perlu menginisiasi variabel itu, dan bertambah setiap kali. Menggunakan enumerate()menyimpan seperti 3 baris kode. Ini berguna saat berurusan dengan hal-hal lain, seperti memproses item dalam daftar. Lihat docs.python.org/2/library/functions.html#enumerate
Sergiy Kolodyazhnyy
@ LéoLéopoldHertz 준영 jika Anda mengerti menggunakan penghitung seperti yang saya lakukan dalam bashcontoh, maka jangan ragu untuk menggunakan itu :) Saya baru saja menemukan dari pengalaman enumerate()menjadi lebih elegan, tetapi itu hanya pendapat saya. Dengan segala cara, gunakan metode lain jika Anda pikir itu lebih jelas
Sergiy Kolodyazhnyy
OK, enumeratelebih jelas daripada instantiasi variabel. Bisakah ekspresi lambda menghemat ruang?
Léo Léopold Hertz 준영
@ LéoLéopoldHertz 준영 Ini bisa menghemat ruang dalam skrip yang panjang, tetapi dalam kasus ini, saya hanya tidak melihat bagaimana itu bisa membantu.
Sergiy Kolodyazhnyy
2

Ini juga merupakan opsi menggunakan cat -npenomoran otomatis:

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