Saya memiliki file teks dengan format berikut. Baris pertama adalah "KEY" dan baris kedua adalah "VALUE".
KEY 4048:1736 string
3
KEY 0:1772 string
1
KEY 4192:1349 string
1
KEY 7329:2407 string
2
KEY 0:1774 string
1
Saya membutuhkan nilai di baris yang sama dengan kunci. Jadi hasilnya akan terlihat seperti ini ...
KEY 4048:1736 string 3
KEY 0:1772 string 1
KEY 4192:1349 string 1
KEY 7329:2407 string 2
KEY 0:1774 string 1
Akan lebih baik jika saya bisa menggunakan pembatas seperti $
atau ,
:
KEY 4048:1736 string , 3
Bagaimana cara menggabungkan dua baris menjadi satu?
pr
,paste
,awk
,xargs
,sed
danpure bash
! (xargs
apakah lebih lambat, lebih lambat dari pada bash !)Jawaban:
awk:
perhatikan, ada baris kosong di akhir output.
sed:
sumber
printf
string ekspansi seperti%s
ditemukan di dalam$0
. Kegagalan itu bisa dihindari seperti ini:'NR%2{printf "%s ",$0;next;}1'
1
setelah kurung kurawal tutup?paste
bagus untuk pekerjaan ini:sumber
paste
Di sisi lain, berperilaku sempurna. +1.cut
tetapi selalu lupapaste
. Ini batu untuk masalah ini. Saya perlu menggabungkan semua baris dari stdin dan melakukannya dengan mudahpaste -sd ' ' -
.-
berarti stdin, begitupaste - -
berarti membaca dari stdin, lalu membaca dari stdin, Anda dapat menumpuk sebanyak mungkin dari yang Anda inginkan.Alternatif untuk sed, awk, grep:
Ini yang terbaik ketika Anda ingin bergabung dengan garis N dan Anda hanya perlu ruang terbatas keluaran.
Jawaban asli saya adalah
xargs -n2
yang memisahkan pada kata-kata daripada garis.-d
dapat digunakan untuk membagi input dengan sembarang karakter tunggal.sumber
-d '\n'
xargs
pengguna biasa tapi tidak tahu ini. Tip yang bagus.Ada lebih banyak cara untuk membunuh anjing daripada menggantung. [1]
Masukkan pembatas apa pun yang Anda suka di dalam tanda kutip.
Referensi:
sumber
$0
. Thegetline
perintah juga meraih "berikutnya" garis masukan dan tempat-tempat itu di$0
. Jadi pernyataan pertama mengambil baris pertama, dan perintah cetak menggabungkan apa yang disimpan dalam variabelkey
dengan string yang mengandung koma, bersama dengan baris yang diambil menggunakangetline
. Lebih jelas? :)Inilah solusi saya di bash:
sumber
Meskipun tampaknya solusi sebelumnya akan berhasil, jika terjadi anomali tunggal dalam dokumen, hasilnya akan hancur berkeping-keping. Di bawah ini sedikit lebih aman.
sumber
/KEY/
harus dilakukan Apa yangp
dilakukan di akhir?/KEY/
pencarian untuk sejalan denganKEY
. yangp
mencetak hasilnya. ini lebih aman karena hanya menerapkan operasi pada baris denganKEY
di dalamnya.Inilah cara lain dengan
awk
:Seperti yang ditunjukkan oleh Ed Morton dalam komentar, lebih baik menambahkan kawat gigi untuk keamanan dan paritas untuk portabilitas.
ORS
singkatan dari Output Record Separator. Apa yang kami lakukan di sini adalah menguji suatu kondisi menggunakanNR
yang menyimpan nomor baris. Jika modulo dariNR
adalah nilai sebenarnya (> 0) maka kita mengatur Output Field Separator ke nilaiFS
(Field Separator) yang secara default adalah spasi, selain itu kita menetapkan nilaiRS
(Record Separator) yang merupakan baris baru.Jika Anda ingin menambahkan
,
sebagai pemisah kemudian gunakan yang berikut:sumber
ORS
dan itu sedang diperlakukantrue
karena ORS mendapatkan nilai yang bukan nol atau string nol dan awks menebak dengan benar bahwa itu harus menjadi sengatan daripada perbandingan numerik? Apakah ini sesuatu yang lain? Saya benar-benar tidak yakin dan saya akan menuliskannya sebagaiawk '{ORS=(NR%2?FS:RS)}1' file
. Saya tanda kurung ekspresi ternary untuk memastikan portabilitas juga."ex" adalah editor baris skrip yang berada dalam keluarga yang sama dengan sed, awk, grep, dll. Saya pikir mungkin itu yang Anda cari. Banyak klon / penerus vi modern juga memiliki mode vi.
Ini mengatakan untuk setiap baris, jika cocok dengan "KEY" melakukan j oin dari baris berikut. Setelah itu perintah Rampungkan (terhadap semua baris), mengeluarkan w ritus dan q uit.
sumber
Jika Perl adalah opsi, Anda dapat mencoba:
sumber
-0
diperintahkan untuk mengatur pemisah rekaman ($/)
ke nol, sehingga kita dapat menjangkau beberapa baris dalam pola yang cocok. Halaman ini agak terlalu teknis bagi saya untuk mencari tahu apa artinya dalam praktik.Anda dapat menggunakan awk seperti ini untuk menggabungkan 2 pasang garis:
sumber
Solusi lain menggunakan vim (hanya untuk referensi).
Solusi 1 :
Buka file dalam vim
vim filename
, lalu jalankan perintah:% normal Jj
Perintah ini sangat mudah dimengerti:
Setelah itu, simpan file dan keluar dengan
:wq
Solusi 2 :
Jalankan perintah di shell
vim -c ":% normal Jj" filename
,, lalu simpan file dan keluar bersama:wq
.sumber
norm!
lebih kuat kalaunormal
-kalauJ
sudah dipetakan ulang. +1 untuk solusi vim.Anda juga dapat menggunakan perintah vi berikut:
sumber
:%g//j
karena semua yang Anda butuhkan adalah pertandingan untuk bergabung akan dieksekusi, dan null string masih regex valid.//
, pola pencarian sebelumnya akan digunakan sebagai gantinya. Jika tidak ada pola sebelumnya, Vim hanya melaporkan kesalahan dan tidak melakukan apa pun. Solusi Jdamian bekerja setiap saat.Sedikit variasi pada jawaban glenn jackman menggunakan
paste
: jika nilai untuk-d
opsi pembatas berisi lebih dari satu karakter,paste
siklus melalui karakter satu per satu, dan dikombinasikan dengan-s
opsi terus melakukan itu sambil memproses file input yang sama.Ini berarti bahwa kita dapat menggunakan apa pun yang ingin kita miliki sebagai pemisah ditambah urutan pelarian
\n
untuk menggabungkan dua garis sekaligus.Menggunakan koma:
dan tanda dolar:
Apa yang tidak bisa dilakukan adalah menggunakan pemisah yang terdiri dari beberapa karakter.
Sebagai bonus, jika
paste
POSIX compliant, ini tidak akan mengubah baris baru dari baris terakhir dalam file, jadi untuk file input dengan jumlah baris ganjil sepertipaste
tidak akan menempel pada karakter pemisahan pada baris terakhir:sumber
Ini berbunyi sebagai
sumber
Dalam kasus di mana saya perlu menggabungkan dua baris (untuk pemrosesan lebih mudah), tetapi memungkinkan data melewati spesifik, saya menemukan ini berguna
data.txt
output kemudian terlihat seperti:
convert_data.txt
sumber
Pendekatan lain menggunakan vim adalah:
Ini berlaku a
join
(ke baris di bawahnya) untuk semua baris yang memiliki kataKEY
di dalamnya. Hasil:sumber
Cara paling sederhana ada di sini:
sumber
-0
melahap seluruh file alih-alih membacanya baris demi baris;pE
membungkus kode dengan lingkaran dan mencetak hasilnya, lihat detail di http://perldoc.perl.org/perlrun.html ;^KEY
cocokkan "KEY" di awal baris, diikuti oleh pertandingan yang tidak serakah dari apa pun (.*?
) sebelum urutan\s+
apa pun termasuk jeda baris;(\d+)
yang kami tangkap dan kemudian masukkan kembali sebagai$1
;diikuti oleh akhir baris
$
.\K
dengan mudah mengecualikan semua yang ada di sisi kirinya dari pergantian jadi{ $1}
hanya menggantikan 1-2 urutan, lihat http://perldoc.perl.org/perlre.html .sumber
Solusi yang lebih umum (memungkinkan lebih dari satu jalur tindak lanjut untuk digabungkan) sebagai skrip shell. Ini menambahkan garis di antara masing-masing, karena saya membutuhkan visibilitas, tetapi itu mudah diatasi. Contoh ini adalah di mana baris "kunci" berakhir: dan tidak ada baris lain yang melakukannya.
sumber
Coba baris berikut:
Letakkan pembatas di antara keduanya
mis. jika pembatas adalah
|
, maka:sumber
Anda bisa menggunakan
xargs
seperti ini:sumber
xargs -n 2
tetapi jawaban ini tidak menjelaskan ini sama sekali.