Menambahkan Kolom nilai dalam file yang dibatasi tab

17

Bagaimana saya bisa menambahkan Kolom nilai dalam file yang memiliki jumlah baris tertentu. Saya memiliki file input seperti ini:

File input:

SPATA17 1   217947738
LYPLAL1 1   219383905
FAM47E  4   77192838
SHROOM3 4   77660162
SHROOM3 4   77660731
SHROOM3 4   77662248

Berkas keluaran:

SPATA17 1   217947738 file1
LYPLAL1 1   219383905 file1
FAM47E  4   77192838  file1
SHROOM3 4   77660162  file1
SHROOM3 4   77660731  file1
SHROOM3 4   77662248  file1

Dalam hal ini, saya ingin menambahkan Kolom nilai, hingga jumlah baris dalam file. Nilai tetap konsisten, seperti "file1".

Alasannya adalah saya memiliki 100 file-file itu. Saya tidak ingin membuka setiap file dan menempelkan sebuah kolom. Juga apakah ada cara untuk mengotomatisasi ini, dengan masuk ke direktori dan menambahkan kolom nilai. Nilai berasal dari nama file, yang harus ditambahkan di setiap baris file di kolom terakhir / pertama.

Ron
sumber

Jawaban:

22

Anda dapat menggunakan loop satu-liner seperti ini:

for f in file1 file2 file3; do sed -i "s/$/\t$f/" $f; done

Untuk setiap file dalam daftar, ini akan digunakan seduntuk menambahkan tab dan nama file pada akhir setiap baris.

Penjelasan:

  • Menggunakan -ibendera dengan seduntuk melakukan penggantian di tempat, menimpa file
  • Lakukan penggantian dengan s/PATTERN/REPLACEMENT/. Dalam contoh ini POLA adalah $, akhir baris, dan PENGGANTIAN adalah \t(= a TAB), dan $fmerupakan nama file, dari variabel loop. The s///perintah dalam tanda kutip ganda sehingga shell dapat memperluas variabel.
janos
sumber
Kode berfungsi. Bisakah Anda menjelaskan konten dalam tanda kutip?
Ron
Sama seperti "awk" digunakan saat bekerja dengan kolom, adalah 'sed' juga digunakan untuk situasi yang sama. Saya pemula untuk 'awk' dan 'sed'.
Ron
@Ron sedpaling praktis untuk penggantian pola dan penghematan di tempat. Untuk keperluan Anda menyimpan file, itu adalah opsi yang relatif nyaman. Jika Anda tidak perlu menulis kembali ke file yang sama dengan yang Anda proses, maka awkbiasanya lebih mudah untuk dikerjakan.
janos
Secara pribadi, saya sering tersandung oleh awkpemisah bidang input / output, jadi cobalah untuk menghindari menggunakannya kapan pun memungkinkan, menjadikan sedlebih menarik.
user5359531
11

Ayo mengapa kalian merekomendasikan alat-alat yang ampuh ketika ada pasteperintah!

$ cat a
A
B
C
D
$ cat b
1
2
3
4
$ paste a b
A   1
B   2
C   3
D   4

Dengan sedikit tipu daya, Anda bisa menggunakan pasteuntuk tujuan OP. Namun, itu tidak akan menggantikan file di tempat:

for f in file1 file2 file3; do 
    paste $f <(yes $f | head -n $(cat $f | wc -l)) > $f.new
done

Ini akan menempelkan nama file masing-masing sebagai kolom terakhir dari setiap file ke file baru filename.new

yegle
sumber
Terima kasih! pastejelas merupakan permata tersembunyi.
neu242
10

Anda bisa menggunakan awk:

awk '{print $0, FILENAME}' file1 file2 file3 ...
cuonglm
sumber
Karena setiap file memiliki nama yang berbeda, jadi saya harus melakukan ini 100 kali. Apakah ada cara untuk melakukannya sekali?
Ron
Tidak, FILENAMEadalah variabel dalam awk, itu diperluas ke nama file saat ini yang awksedang diproses. Anda cukup melakukannya satu, beri makan semua file awk.
cuonglm
ok, tetapi bagaimana mengarahkan output ke file baru, dari setiap file? apakah awk menyimpan setiap file saat memproses?
Ron
Jika sudah GNU awk 4.1.0atau lambat, Anda bisa menggunakannya -iuntuk mengedit inplace. Jika tidak, Anda harus mengarahkan ulang awkouput ke file temp, kemudian gunakan grepuntuk mengekstrak baris dari setiap file.
cuonglm
Anda bisa melakukannyafor file in *; do awk 'BEGIN{OFS="\t"}{print $0, FILENAME}' $file; done
fedorqui