Làm cách nào để xử lý tệp văn bản nhiều cột để có được tệp văn bản nhiều cột khác?


17

Tôi có một tập tin văn bản:

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

Làm cách nào tôi có thể xử lý tệp đó và nhận tệp 2 cột như thế này:

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

Hoặc một tệp ba cột như thế này:

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

Tôi thích nhận được giải pháp awk nhưng các giải pháp khác cũng được hoan nghênh.

Câu trả lời:


1

Bạn cũng có thể làm điều đó với một lệnh gọi GNU awk:

định hình lại

# 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"
}

Chạy nó như thế này:

awk -f reshape.awk n=2 infile

Hoặc như một lớp lót:

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

Đầu ra:

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

Hoặc với 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

Điều này không sử dụng $1như là chuỗi định dạngprintf ?
tự đại diện

@Wildcard: Đúng vậy, an toàn hơn khi sử dụng "%s", .... Cập nhật
Thor

Cảm ơn về lời xác nhận. :) Nhân tiện, áp dụng tương tự cho awklệnh trong câu trả lời khác của bạn cho câu hỏi này.
Wildcard

20

Đặt mỗi trường trên một dòng và hậu cột.

Mỗi trường trên một dòng

tr

tr -s ' ' '\n' < infile

grep

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

quyến rũ

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

hoặc di động hơn:

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

ôi

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

hoặc là

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

Cột

dán

Đối với 2 cột:

... | paste - -

Đối với 3 cột:

... | paste - - -

Vân vân.

quyến rũ

Đối với 2 cột:

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

Đối với 3 cột:

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

Vân vân.

xargs

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

Khi xargssử dụng /bin/echođể in, hãy cẩn thận rằng dữ liệu trông giống như các tùy chọn echosẽ được hiểu như vậy.

ôi

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

pr

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

hoặc là

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

cột (từ gói autogen)

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

Sản lượng tiêu biểu:

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
Up rổ. +1 thưa ngài
Steven Penny

Không nên xargsgọi điện thoại echohay printfkhông?
tự đại diện

1
@Wildcard: xargscác cuộc gọi /bin/echotheo mặc định
Thor

1
Wow, tôi không có ý tưởng! Nó thậm chí còn được chỉ định bởi POSIX . Cảm ơn!
Wildcard

@Wildcard: Gửi dữ liệu đến xargsđó trông giống như các tùy chọn /bin/echogây ra sự cố ... Tôi đã thêm một cảnh báo.
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

Như Wildcard đã chỉ ra, điều này sẽ chỉ hoạt động nếu tệp của bạn được định dạng độc đáo, trong đó không có bất kỳ ký tự đặc biệt nào mà trình bao sẽ diễn giải thành các khối và bạn hài lòng với các quy tắc phân tách từ mặc định. Nếu có bất kỳ câu hỏi nào về việc liệu các tệp của bạn sẽ "vượt qua" bài kiểm tra đó, không sử dụng phương pháp này.

Một khả năng sẽ là sử dụng printfđể làm điều đó như thế nào

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

Điều đó sẽ thực hiện phân tách từ trên nội dung của your_filevà sẽ ghép chúng và in chúng với các tab ở giữa. Bạn có thể sử dụng nhiều %schuỗi định dạng hơn printfđể có thêm cột.


1
Các phụ thuộc vào các tập tin không chứa ký tự đặc biệt. Ví dụ, nếu có dấu hoa thị (*), bạn sẽ nhận được kết quả rất bất ngờ.
tự đại diện

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

(thay 4 bằng số cột)


4

rsTiện ích BSD (định hình lại):

$ 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 2hàngcột . Chỉ định 0có nghĩa là "tính toán các hàng tự động từ các cột".


3

Phương pháp tiếp cận kịch bản Python.

Ý tưởng cơ bản ở đây là làm phẳng tất cả các từ trong văn bản của bạn thành một danh sách, sau đó in dòng mới sau mỗi mục thứ hai (đó là để phân loại thành hai cột). Nếu bạn muốn 3 cột, hãy đổi index%2thànhindex%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 = []

Đầu ra mẫu:

$ 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

Phiên bản ba cột (như đã nói ở trên, chỉ index%3 == 0thay đổi)

$ 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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.