Bagaimana cara memproses file teks multi kolom untuk mendapatkan file teks multi kolom lainnya?


17

Saya punya file teks:

a   aa  aaa     b   bb  bbb     c   cc  ccc
d   dd  ddd     e   ee  eee     f   ff  fff
g   gg  ggg     h   hh  hhh     i   ii  iii
j   jj  jjj

Bagaimana saya bisa memprosesnya dan mendapatkan file 2 kolom seperti ini:

a   aa
aaa b
bb  bbb
c   cc
ccc d
dd  ddd
e   ee
eee f
ff  fff
g   gg
ggg h
hh  hhh
i   ii
iii j
jj  jjj

Atau file tiga kolom seperti ini:

a   aa  aaa
b   bb  bbb
c   cc  ccc
d   dd  ddd
e   ee  eee
f   ff  fff
g   gg  ggg
h   hh  hhh
i   ii  iii
j   jj  jj

Saya lebih suka mendapatkan solusi awk tetapi solusi lain juga disambut.

Jawaban:


1

Anda juga dapat melakukannya dengan satu permintaan GNU awk:

membentuk ulang

# Set awk to split input at whitespace characters and
# use tab as the output field separator 
BEGIN {
  RS="[ \t\n]+"
  OFS="\t"
}

# Print using OFS or ORS based on the element index
{
  printf "%s", $1 (NR%n == 0 ? ORS : OFS)
}

# Append a missing new-line when last row is not full
END { 
  if( NR%n != 0) 
    printf "\n"
}

Jalankan seperti ini:

awk -f reshape.awk n=2 infile

Atau sebagai one-liner:

awk -v n=2 'BEGIN { RS="[ \t\n]+"; OFS="\t" } { printf "%s", $1 (NR%n == 0 ? ORS : OFS) } END { if( NR%n != 0) printf "\n" }' infile

Keluaran:

a   aa
aaa b
bb  bbb
c   cc
ccc d
dd  ddd
e   ee
eee f
ff  fff
g   gg
ggg h
hh  hhh
i   ii
iii j
jj  jjj

Atau dengan n=3:

a   aa  aaa
b   bb  bbb
c   cc  ccc
d   dd  ddd
e   ee  eee
f   ff  fff
g   gg  ggg
h   hh  hhh
i   ii  iii
j   jj  jjj

Bukankah ini digunakan $1sebagai format string printf?
Wildcard

@ Kartu Memori: Benar, lebih aman untuk digunakan "%s", .... Diperbarui
Thor

Terimakasih sudah mengkonfirmasi. :) Hal yang sama berlaku untuk awkperintah di jawaban Anda yang lain untuk pertanyaan ini.
Wildcard

20

Letakkan setiap bidang pada baris dan setelah kolom.

Setiap bidang pada satu baris

tr

tr -s ' ' '\n' < infile

grep

grep -o '[[:alnum:]]*' infile

sed

sed 's/\s\+/\n/g' infile

atau lebih portabel:

sed 's/\s\+/\
/g' infile

awk

awk '$1=$1' OFS='\n' infile

atau

awk -v OFS='\n' '$1=$1' infile

Berbentuk kolom

tempel

Untuk 2 kolom:

... | paste - -

Untuk 3 kolom:

... | paste - - -

dll.

sed

Untuk 2 kolom:

... | sed 'N; s/\n/\t/g'

Untuk 3 kolom:

... | sed 'N; N; s/\n/\t/g'

dll.

xargs

... | xargs -n number-of-desired-columns

Saat xargsdigunakan /bin/echountuk mencetak, berhati-hatilah bahwa data yang kelihatannya seperti opsi echoakan ditafsirkan demikian.

awk

... | awk '{ printf "%s", $0 (NR%n==0?ORS:OFS) }' n=number-of-desired-columns OFS='\t'

pr

... | pr -at -number-of-desired-columns

atau

... | pr -at -s$'\t' -number-of-desired-columns

kolom (dari paket autogen)

... | columns -c number-of-desired-columns

Output khas:

a   aa  aaa
b   bb  bbb
c   cc  ccc
d   dd  ddd
e   ee  eee
f   ff  fff
g   gg  ggg
h   hh  hhh
i   ii  iii
j   jj  jjj

2
Membanting dunk. +1 Pak
Steven Penny

Bukankah seharusnya xargspanggilan saluran echoatau printf?
Wildcard

1
@ Kartu Memori: xargspanggilan /bin/echosecara default
Thor

1
Wow, saya tidak tahu! Itu bahkan ditentukan oleh POSIX . Terima kasih!
Wildcard

@ Kartu Memori: Mengirim data xargsyang sepertinya pilihan /bin/echomenyebabkan masalah ... Saya menambahkan peringatan.
Thor

9
$ sed -E 's/\s+/\n/g' ip.txt | paste - -
a   aa
aaa b
bb  bbb
c   cc
ccc d
dd  ddd
e   ee
eee f
ff  fff
g   gg
ggg h
hh  hhh
i   ii
iii j
jj  jjj

$ sed -E 's/\s+/\n/g' ip.txt | paste - - -
a   aa  aaa
b   bb  bbb
c   cc  ccc
d   dd  ddd
e   ee  eee
f   ff  fff
g   gg  ggg
h   hh  hhh
i   ii  iii
j   jj  jjj

9

Seperti yang ditunjukkan Wildcard, ini hanya akan berfungsi jika file Anda diformat dengan baik, karena tidak ada karakter khusus yang akan ditafsirkan oleh shell sebagai gumpalan dan Anda senang dengan aturan pemisahan kata standar. Jika ada pertanyaan tentang apakah file Anda akan "lulus" tes itu, jangan gunakan pendekatan ini.

Satu kemungkinan akan digunakan printfuntuk melakukannya seperti

printf '%s\t%s\n' $(cat your_file)

Itu akan melakukan pemisahan kata pada konten your_filedan akan memasangkannya dan mencetaknya dengan tab di antaranya. Anda bisa menggunakan lebih banyak %sstring format dalam printfuntuk memiliki kolom tambahan.


1
Itu tergantung pada file yang tidak mengandung karakter khusus. Jika memiliki, misalnya, tanda bintang (*), Anda akan mendapatkan hasil yang sangat tak terduga.
Wildcard

4
perl -n0E 'say s/\s+/ ++$n % 4 ?"\t":"\n"/gre' file

(ganti 4 dengan jumlah kolom)


4

rsUtilitas BSD (membentuk kembali):

$ rs 0 2
a   aa  aaa     b   bb  bbb     c   cc  ccc
d   dd  ddd     e   ee  eee     f   ff  fff
g   gg  ggg     h   hh  hhh     i   ii  iii
j   jj  jjj
[Ctrl-D][Enter]
a    aa
aaa  b
bb   bbb
c    cc
ccc  d
dd   ddd
e    ee
eee  f
ff   fff
g    gg
ggg  h
hh   hhh
i    ii
iii  j
jj   jjj

0 2adalah baris dan kolom . Menentukan 0berarti "menghitung baris secara otomatis dari kolom".


3

Pendekatan skrip python.

Ide dasar di sini adalah untuk meratakan semua kata dalam teks Anda menjadi satu daftar, dan kemudian mencetak baris baru setelah setiap item kedua (itu untuk pengelompokan ke dalam dua kolom). Jika Anda ingin 3 kolom, ubah index%2keindex%3

#!/usr/bin/env python3
import sys

items = [i for l in sys.stdin 
           for i in l.strip().split()]
line = []
for index,item in enumerate(items,1):
    line.append(item)
    if index%2 == 0:
       print("\t".join(line))
       line = []

Output sampel:

$ python recolumnate.py < input.txt                                            
a   aa
aaa b
bb  bbb
c   cc
ccc d
dd  ddd
e   ee
eee f
ff  fff
g   gg
ggg h
hh  hhh
i   ii
iii j
jj  jjj

Versi tiga kolom (seperti yang disebutkan di atas, hanya index%3 == 0diubah)

$ cat recolumnate.py                                                           
#!/usr/bin/env python3
import sys

items = [i for l in sys.stdin 
           for i in l.strip().split()]
line = []
for index,item in enumerate(items,1):
    line.append(item)
    if index%3 == 0:
       print("\t".join(line))
       line = []

$ python recolumnate.py < input.txt                                            
a   aa  aaa
b   bb  bbb
c   cc  ccc
d   dd  ddd
e   ee  eee
f   ff  fff
g   gg  ggg
h   hh  hhh
i   ii  iii
j   jj  jjj
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.