Saya memiliki lebih dari 1000 baris dalam sebuah file. File dimulai sebagai berikut (nomor baris ditambahkan):
Station Name
Station Code
A N DEV NAGAR
ACND
ABHAIPUR
AHA
ABOHAR
ABS
ABU ROAD
ABR
Saya perlu mengonversikan ini ke file, dengan entri yang dipisahkan koma dengan menggabungkan setiap dua baris. Data akhir akan terlihat seperti
Station Name,Station Code
A N DEV NAGAR,ACND
ABHAIPUR,AHA
ABOHAR,ABS
ABU ROAD,ABR
...
Apa yang saya coba adalah - mencoba menulis skrip shell dan kemudian echo
mereka dengan koma di antaranya. Tapi saya kira satu-liner efektif sederhana akan melakukan pekerjaan di sini mungkin di sed
/ awk
.
Ada ide?
Jawaban:
Cukup gunakan
cat
(jika Anda suka kucing ;-)) danpaste
:Penjelasan:
paste
membaca dari sejumlah file dan menempel bersama-sama baris yang sesuai (baris 1 dari file pertama dengan baris 1 dari file kedua dll):Alih-alih nama file, kita bisa menggunakan
-
(dash).paste
mengambil baris pertama dari file1 (yang merupakan stdin). Kemudian, ia ingin membaca baris pertama dari file2 (yang juga stdin). Namun, karena baris pertama stdin sudah dibaca dan diproses, yang sekarang menunggu di aliran input adalah baris kedua dari stdin, yangpaste
dengan senang hati menempel pada baris pertama. The-d
pilihan menetapkan pembatas menjadi koma daripada tab.Atau, lakukan
PS Ya, orang dapat menyederhanakan hal di atas
atau
yang memiliki keuntungan karena tidak menggunakan
cat
.Namun, saya tidak menggunakan idiom ini dengan sengaja , untuk alasan kejelasan - ini kurang verbose dan saya suka
cat
(CATS ARE NICE). Jadi tolong jangan edit.Atau, jika Anda lebih suka menempelkan ke kucing (tempel adalah perintah untuk menggabungkan file secara horizontal, sementara kucing menggabungkannya secara vertikal), Anda dapat menggunakan:
sumber
paste
perintah sempurna bekerja, bisa tolong beri sedikit penjelasan lebih lanjut tentang hal itu. Tanda hubung ???cat
argumen Anda . Tidaksed "N;s/\n/,/" file.in > file.out
bekerjaJika ada orang yang mendarat di sini ingin menggabungkan semua baris ke dalam CSV one liner, coba
sumber
Menggunakan sed, gabung (N) setiap 2 baris, dan ganti baris baru (\ n) dengan ",".
sumber
Perhatikan juga bahwa karena kita hanya mengganti satu karakter dengan yang lain (setiap baris baru dengan koma), kita dapat mengerjakan file input yang ada:
(tapi waspadalah itu mungkin tidak bekerja pada sistem non-Unix yang memiliki terminator CRLF (seperti yang Microsoft) yang
paste
mungkin ditangani oleh beberapa POSIX yang ditiru dengan cara yang bukan Unix)sumber
1
sedang dilakukan di sini1<>
? apakah itu salah cetak?Berikut ini adalah satu-liner (meskipun berpotensi jutaan-perintah-run-er) menggunakan Bash murni:
Saya menggunakan subkulit (paranthesis) sehingga saya tidak perlu menyimpan dan mengembalikan
IFS
. Yang mana yang seharusnya dilakukan agar tidak mengacaukan lingkungan pengguna jika sumbernya bersumber. Alternatif akan terjadilah bahwa IFS baru hanya untukread
seperti diIFS= read -r name
,IFS= read -r code
.Fakta bahwa semua perintah dalam loop dibangun di shell membuat kinerjanya dapat diterima dan bahkan lebih cepat daripada solusi lain untuk file kecil. Tetapi banyak orang akan menganggapnya sebagai praktik yang buruk dan seseorang harus berhati-hati ketika menggeneralisasikannya dengan hal lain.
sumber
while IFS='\n' read -r name; do IFS='\n' read -r code ... done < file.in
, yang merupakan ungkapan yang sering saya lihat dalam skrip shell. The-r
bendera untukread
berarti "menafsirkan karakter '\' diikuti oleh karakter 'n' dalam aliran stdin sebagai dua karakter, bukan sebagai baris baru." Bisa dibilang, mungkin lebih estetika untuk membuat subkulit seperti yang Anda lakukan daripada mengulangiIFS='\n'
.-r
ditingkatkan secara teknis. Besar! Saya bukan penggemar gagasan melewati perubahanIFS
dua kali. Kalau saya pernah menggunakan satu baca, super bagus, tetapi tidak dua kali. Tentu saja itu masalah pendapat . Menggunakan subkulit sedikit lebih dari pengetahuan Bash umum saya akan mengatakan, sehingga banyak orang akan mengalami kesulitan memahami tujuannya. Itu hal yang buruk.Untuk rangkaian jawaban yang lengkap,
awk
solusi yang mungkin adalah:sumber
printf
? Akan gagal dalam kasus yang jarang terjadi ketika nama stasiun berisi penentu format. (Lihat pastebin.com/wgxFttrJ untuk contoh.) Tapi ini hanya tebakan, downvote bukan dari saya.Hoary berangan
awk
idiom tuasumber
awk '{ORS=NR%2?",":"\n"};1'
lebih pendek dan lebih banyak idiomprint
dan maksudnya jelas.1
sama jelasnya denganawk
tangan tua seperti saya tapi saya lebih sukaprint
sed
sebentar sebelum mencari, tetapiawk
membuat menggabungkan setiap 4 baris lebih mudah. Menyelamatkan saya perjalanan ke$EDITOR
!Mungkin dengan perl juga,
perl -pe 's/^\d+\.\s+//;$.&1?chomp:print","' file
sumber
Sebagai contoh:
Output: (catatan:
xargs -L number_of_columns
berfungsi baik dengan sebagian besar jumlah kolom tidak hanya setiap dua baris)sumber
Solusi POSIX dengan
pr
:http://pubs.opengroup.org/onlinepubs/9699919799/utilities/pr.html
sumber