Apakah mungkin dengan Gedit atau baris perintah untuk mengubah setiap baris keempat file teks?

11

Saya mencoba mengonversi file teks menjadi spreadsheet yang dipisahkan dengan tab. File teks saya kira-kira seperti ini:

Dog
Cat
Fish
Lizard
Wolf
Lion
Shark
Gecko
Coyote
Puma
Eel
Iguana

Dengan fungsi pencarian dan penggantian standar di Gedit atau LibreOffice, mudah untuk mengganti ujung baris dengan sebuah tab. Tetapi jika saya hanya menukar pengembalian carriage dengan tab, saya akan mendapatkan ini:

Dog   Cat   Fish   Lizard   Wolf   Lion   Shark   Gecko   Coyote   Puma   Eel   Iguana

Tapi yang perlu saya lakukan adalah membuatnya terlihat seperti ini:

Dog   Cat   Fish   Lizard
Wolf   Lion   Shark   Gecko  
Coyote   Puma   Eel   Iguana

Jadi, dapatkah saya menukar setiap ujung karakter baris dengan tab kecuali untuk setiap baris keempat?

Saya tidak tahu apakah iterasi bersyarat semacam itu dapat dilakukan dengan ekspresi reguler di dalam program seperti Gedit atau LibreOffice, jadi mungkin ini perlu semacam fungsi baris perintah? Saya bahkan tidak jelas apa alat terbaik untuk memulai.


Memperbarui:

Saya mencoba perintah berikut:

sed 'N;N;N;s/\n/\t/g' file > file.tsv

paste - - - - < file > file.tsv

pr -aT -s$'\t' -4 file > file.tsv

xargs -d '\n' -n4 < inputfile.txt

Tetapi ketika saya mencoba untuk membuka tsvfile yang dihasilkan di LibreOffice, kolomnya kurang tepat. Saya tidak yakin apakah ini berarti saya tidak menjalankan perintah di atas dengan benar, atau jika saya melakukan sesuatu yang salah dalam fungsi impor LibreOffice:

Pembukaan TSV di Calc

Hanya untuk referensi, hasil yang diinginkan akan terlihat seperti ini:

Kolom yang tepat

Penanya
sumber

Jawaban:

16

Anda bisa menggunakan editor baris perintah sepertised

sed 'N;N;N;s/\n/\t/g' file > file.tsv

atau, lebih terprogram, dengan menambahkan karakter garis lanjutan garis miring terbalik ke masing-masing baris yang ingin Anda gabungkan menggunakan n skip moperator alamat GNU sed dan mengikutinya dengan satu garis klasik untuk bergabung dengan garis lanjutan:

sed '0~4! s/$/\t\\/' file | sed -e :a -e '/\\$/N; s/\\\n//; ta'

Lihat misalnya Sed One-Liners Dijelaskan :

  1. Tambahkan baris ke baris berikutnya jika diakhiri dengan garis miring terbalik "\".

    sed -e :a -e '/\\$/N; s/\\\n//; ta'
    

Namun IMHO akan lebih mudah dengan salah satu utilitas pemrosesan teks standar lainnya mis

paste - - - - < file > file.tsv

(jumlah -akan sesuai dengan jumlah kolom) atau

pr -aT -s$'\t' -4 file > file.tsv

(Anda dapat menghilangkan -s$'\tjika Anda tidak keberatan output dipisahkan oleh banyak tab).


Perilaku re-import aneh yang Anda amati hampir pasti karena file asli memiliki ujung garis CRLF gaya Windows. Jika Anda perlu bekerja dengan file dari Windows, maka Anda dapat memutar konversi ke perintah dengan berbagai cara misalnya

tr -d '\r' < file.csv | paste - - - -

atau

sed 'N;N;N;s/\r\n/\t/g' file.csv

Yang pertama akan menghapus semua pengembalian carriage sedangkan yang terakhir akan mempertahankan CR di akhir setiap baris baru (yang mungkin apa yang Anda inginkan jika pengguna akhir yang dimaksud ada di Windows).

Steeldriver
sumber
1
Catatan tentang ujung garis gaya Windows: alat standar untuk mengkonversi antara mereka dan gaya Unix adalah dos2unixdan unix2dos.
David Foerster
13

Anda dapat menggunakan xargsuntuk selalu mengelompokkan empat baris menjadi satu, masing-masing dipisahkan dengan satu ruang:

xargs -d '\n' -n4 < inputfile.txt

-d '\n'menyetel pembatas input ke karakter baris baru, jika tidak maka akan memecah spasi. Jika Anda hanya memiliki satu kata per baris input, Anda bahkan dapat menghilangkannya.
-n4set nomor argumen (jumlah item input per jalur output) ke 4.

Keluaran:

Dog Cat Fish Lizard
Wolf Lion Shark Gecko
Coyote Puma Eel Iguana

Atau jika Anda ingin tab sebagai pemisah alih-alih spasi, Anda dapat menggantinya sesudahnya. Namun, jika Anda memiliki spasi di jalur input Anda, itu akan diganti juga:

xargs -d '\n' -n4 | tr ' ' '\t'

Output (lihat tergantung pada lebar tab browser / terminal):

Dog Cat Fish    Lizard
Wolf    Lion    Shark   Gecko
Coyote  Puma    Eel Iguana
Komandan Byte
sumber
Metode ini memiliki manfaat yang berperilaku wajar bahkan ketika jumlah total garis input bukan kelipatan empat.
Eliah Kagan
3

Anda juga bisa menggunakan:

awk -v ORS="" '{print $1; print NR%4==0?"\n":"\t"}' file > file.tsv 

Dua variabel bawaan awk adalah:

  • ORS: O utput R ecord S eparator (default = newline). Itu ditambahkan di akhir setiap perintah cetak.
  • NR: N Banyaknya arus R ow awk adalah pengolahan.

Perintah ini akan, untuk setiap baris, menampilkan konten kolom pertama (dan hanya di sini). Kemudian ia memilih untuk menambahkan baris baru atau tab dengan menguji sisa pembagian NRdengan 4.

arauk
sumber
3

awkPendekatan terpendek lainnya :

awk '{printf $0 (NR%4?"\t":"\n")}' infile

Ini printf hanya satu kolom diikuti oleh berikutnya dan berikutnya dan ... dan Tab \tkarakter setelah masing-masing tapi akan printf sebuah \nkarakter ewline ketika N Banyaknya R ecord adalah faktor 4 (di mana NR%4akan kembali 0 (false) yang adalah apa yang Ternary Operator condition(s)?when-true:when-falsesedang melakukan.)

αғsнιη
sumber
3

Solusi saya untuk ini adalah dengan menggunakan kombinasi seddan sed. Pertama, Anda dapat menandai setiap baris keempat dengan beberapa karakter khusus, misalnya >, menggunakan solusi ini:

Dalam hal ini Anda ingin memulai dari baris 5 dan menandai setiap baris ke-4 setelahnya. Di GNU seditu bisa diberikan sebagai alamat 5~4. Anda dapat menggunakan perintah ini:

sed '5~4s/^/>/' file1 > file2

Maka Anda perlu menghapus baris baru, yang bisa dilakukan dengan sedloop:

sed ':a;N;s/\n/ /;ba' file2 > file3

Ada cara yang lebih mudah untuk mengonversi baris baru ke beberapa karakter lain, misalnya dengan tr:

tr '\n' ' ' < file2 > file3

Either way, menggabungkan keduanya memberi

Dog   Cat   Fish   Lizard   >Wolf   Lion   Shark   Gecko   >Coyote   Puma   Eel   Iguana

( sedversi meninggalkan baris tambahan, sedangkan trversi tidak)

Setelah itu, Anda hanya perlu mengonversi karakter khusus yang Anda masukkan ke baris baru; lihat misalnya Konversikan file yang dibatasi-tab untuk menggunakan baris baru . Dalam hal ini, ubah >ke baris baru:

sed 'y/>/\n/' file3 > outfile

The yperintah melakukan fungsi yang sama seperti tr, mengubah satu karakter ke lain, tetapi Anda dapat menggunakan sperintah di sini sama baiknya. Dengan s, Anda harus gberoperasi pada setiap pertandingan di baris ( sed 's/>/\n/g').

Daripada membuat dua file perantara, Anda bisa menggunakan pipa:

$ sed '5~4s/^/>/' file | sed ':a;N;s/\n/ /;ba' | sed 'y/>/\n/'
Dog Cat Fish Lizard 
Wolf Lion Shark Gecko 
Coyote Puma Eel Iguana

Jika spasi tambahan adalah masalah, Anda dapat menambahkan perintah lain untuk menghapusnya:

| sed 's/ $//'
spaceman117X
sumber
2

Demi "kelengkapan" inilah solusi bash murni:

#!/usr/bin/env bash

sep=$'\t'

while read one \
      && read two \
      && read three \
      && read four
do
  printf "%s\n" "$one$sep$two$sep$three$sep$four"
done

Bekerja juga dengan spasi, dengan asumsi IFSdiatur dengan benar (yang seharusnya secara default, AFAIK). Selain itu, saya pikir ini bahkan bisa menjadi skrip shell portabel dan berfungsi dengan shell POSIX yang kompatibel.

Daniel Jour
sumber
1
Ini tidak mudah dibawa ke shell yang kompatibel dengan POSIX pada umumnya, karena $' 'bentuk mengutip tidak diperlukan oleh POSIX. Sebagai contoh, di dash(yang menyediakan shsecara default di Ubuntu), menjalankan printf '%s\n' $'a\tb'hanya output $a\tb. Itu tidak berarti ini tidak berguna; itu bekerja di bash. Namun, seperti halnya dengan beberapa solusi lain yang telah diposting orang, itu menghasilkan output yang tidak lengkap jika jumlah baris input bukan kelipatan empat. Juga, saya sarankan menggunakan read -r, karena tidak ada alasan untuk berpikir perluasan backslash lolos dalam file input yang diinginkan di sini.
Eliah Kagan
Anda bisa melakukannyaprintf '%s\t%s\t%s\t%s\n' "$one" "$two" "$three" "$four"
terdon
2

Makro vim (direkam dengan q) dapat menerapkan operasi Anda, lalu melewati tiga baris. Kemudian, Anda hanya menjalankan makro itu n kali.

misalnya:

qq $ J i <TAB> <ESC> $ J i <TAB> <ESC> $ J i <TAB> <ESC> ^^ j qq 100 @q
pemeras dan prajurit
sumber
2

Karena Anda meminta solusi Gedit, sesuatu seperti ini seharusnya berfungsi:

Temukan:

(\w+)[\r\n]+(\w+)[\r\n]+(\w+)[\r\n]+(\w+)[\r\n]+

Ubah dengan:

\1\t\2\t\3\t\4\n

Pastikan kotak centang untuk ekspresi reguler ditandai.

Bagaimana itu bekerja:

Langkah pertama adalah menemukan serangkaian karakter kata, dengan \ w +, dan menangkap hasilnya dalam variabel \ 1 dengan membungkus tanda kurung di sekitar ekspresi:

(\w+)

Selanjutnya kita mencari serangkaian karakter akhir baris, \ r dan \ n, atau CR dan LF. Karena file berformat Windows menggunakan keduanya, kami membuat kelas karakter dengan membungkus kedua karakter ini dalam tanda kurung siku. Nilai tambah membuatnya mencari satu atau lebih karakter:

[\r\n]+

Akhirnya, kami mengulangi ini 3 kali lebih banyak, menyimpan setiap kata berikutnya dalam variabel \ 2, \ 3, dan \ 4. Ini membuat penggantian kami dengan ekspresi menjadi sederhana. Kami hanya perlu menempatkan karakter tab, \ t, dan karakter baris baru, \ n, di tempat yang sesuai untuk pemformatan yang Anda butuhkan.

Jason Wood
sumber