Cách in hai cột cuối cùng bằng awk


106

Tất cả những gì tôi muốn là in hai cột cuối cùng.


6
Không hoàn toàn chắc chắn tại sao điều này có 87 lượt ủng hộ, nó chắc chắn có thể được cải thiện ít nhất với một ví dụ.
Arj

Có lẽ vì bản chất câu hỏi này cực kỳ đơn giản và dễ hiểu mà không cần ví dụ, điều này hiếm khi xảy ra, nhưng trong trường hợp này, nó có vẻ hoạt động. Vấn đề ở đây tôi nghĩ không phải là thiếu thông tin, mà nhiều hơn là nó cho thấy sự thiếu nghiên cứu độc lập.
DryLabRebel

Câu hỏi này cũng là một bản sao của câu hỏi này .
DryLabRebel

Điều này có trả lời câu hỏi của bạn không? In cột / trường cuối cùng thứ hai trong awk
DryLabRebel

Câu trả lời:


194

Bạn có thể sử dụng biến NFđược đặt thành tổng số trường trong bản ghi đầu vào:

awk '{print $(NF-1),"\t",$NF}' file

điều này giả định rằng bạn có ít nhất 2 trường.


1
Bạn cần có dấu phẩy - vì ngày nay chúng ta đang kén chọn: khoảng trắng nối các trường, dấu phẩy phân tách các trường trong một câu lệnh in. Điều đó sẽ hợp nhất hai lĩnh vực
McNamara jim

18
Bây giờ bạn đang in "trường-OFS-tab-OFS-trường". Nó phải là awk '{print $(NF-1) "\t" $NF}' filehoặc awk '{print $(NF-1), $NF}' filehoặc awk 'BEGIN{OFS="\t"} {print $(NF-1), $NF}' file.
Tạm dừng cho đến khi có thông báo mới.

Chỉ để thêm vào nhận xét trước đó, vấn đề với việc sử dụng '{print $x,"\t",$y}'là awk diễn giải mỗi biến được phân tách bằng dấu phẩy là trường riêng của nó, vì vậy kết quả thực sự sẽ là field1<space><tab><space>field2, (vì nó sẽ sử dụng dấu phân cách khoảng trắng theo mặc định) trái ngược với field1<tab>field2có thể là bạn đang mong đợi. sử dụng Dấu phân tách trường đầu ra (OFS) hầu như luôn là điều bạn muốn.
DryLabRebel

13
awk '{print $NF-1, $NF}'  inputfile

Lưu ý: điều này chỉ hoạt động nếu tồn tại ít nhất hai cột. Trên các bản ghi có một cột, bạn sẽ nhận được"-1 column1"


3
Hãy thử và xem. Nó hoạt động Solaris 9 awk & nawk. Giải pháp thay thế là $ (NF-1)
jim mcnamara

1
@coaddict - Tôi đoán bạn chưa làm việc với các triển khai awk khác nhau. Các hành vi cũ của awks đã được đưa ra (có thể sai lầm). Tôi không có cách nào để kiểm tra - đó có thể là những gì bạn đang tham khảo. Vì vậy, tôi không biết chắc chắn tại sao bình luận của bạn lại xuất hiện ở mức thấp. Linux awk ra khỏi hộp thường là trố mắt. Tôi sẽ kiểm tra và đăng lại. Trong khi đó, hãy thử Soalris hoặc HPUX hoặc DGX hoặc bất cứ thứ gì để xem ý tôi là awk cũ.
jim mcnamara

6
Bạn có thể bị lừa khi nghĩ rằng nó hoạt động vì bạn đã thử echo 1 2 3 | awk .... $NF-1($NF) - 1trong mọi awktriển khai.
Stephane Chazelas

Mã nguồn "One True Awk" có hơn 40 xung đột về yaccngữ pháp, điều này thật trớ trêu khi chữ A là viết tắt của awk. Các phiên bản khác nhau của awk phân tích cú pháp mọi thứ khác nhau? Bất ngờ lớn!
Kaz

1
@THESorcerer, hãy thử với echo '5 4 3 2 1' | awk '{print $NF-1,$NF; print $(NF-1), $NF}'- hoặc bất kỳ đầu vào nào khác trong đó trường cuối cùng thứ 2 không nhỏ hơn trường cuối cùng một lần.
glenn Jackman

6

McNamara @jim: hãy thử sử dụng dấu ngoặc đơn cho khoảng NF, tức $(NF-1)$(NF)thay $NF-1$NF(các công trình trên Mac OS X 10.6.8 cho FreeBSD awkgawk).

echo '
1 2
2 3
one
one two three
' | gawk '{if (NF >= 2) print $(NF-1), $(NF);}'

# output:
# 1 2
# 2 3
# two three

Chúng tôi đã xem xét () trước đó. Tôi nghĩ rằng chúng ta đang thảo luận về hành vi awk cũ ban đầu đến từ đâu.
jim mcnamara

+1 cho một câu trả lời rõ ràng $(NF-1)- mà ít nhất là linh hoạt hơn $NF-1; nó chắc chắn ít mơ hồ hơn. $(NF)là quá mức cần thiết, mặc dù - chỉ $NFsẽ làm. Việc bảo vệ chống lại các dòng có ít hơn 2 cột cũng đáng giá, vì với các dòng một cột, bạn sẽ nhận được giá trị cột đầu tiên hai lần và với cột 0 - tức là các dòng trống - lệnh awk sẽ hoàn toàn thất bại, do một nỗ lực để truy cập trường có chỉ mục -1.
mklement0

1

sử dụng gawk cho thấy vấn đề:

 gawk '{ print $NF-1, $NF}' filename
1 2
2 3
-1 one
-1 three
# cat filename
1 2
2 3
one
one two three

Tôi chỉ đặt gawk trên Solaris 10 M4000: Vì vậy, gawk là lý thuyết của vấn đề $ NF-1 so với $ (NF-1). Câu hỏi tiếp theo POSIX nói gì? mỗi:

http://www.opengroup.org/onlinepubs/009695399/utilities/awk.html

Không có hướng này hay cách khác. Không tốt. gawk ngụ ý phép trừ, các awk khác ngụ ý số trường hoặc phép trừ. hmm.


1
2 dòng đầu tiên của tệp đầu vào mẫu của bạn không hữu ích ở chỗ chúng tạo ra cùng một đầu ra với một trong hai hành vi. Bạn có thể vui lòng xác nhận lại rằng Solaris awk thực sự KHÔNG cư xử như trố mắt trong trường hợp này không?
mklement0

Đối với liên kết của bạn đến thông số kỹ thuật awk: Đối số phổ biến để sử dụng $(NF-1)là hai ví dụ về tính toán chỉ mục trường trong thông số kỹ thuật đều sử dụng dạng đó: $(NF-1)$(NF+2). Sau đó, có phần "Biểu thức trong awk", được liệt kê $exprlà có mức độ ưu tiên cao hơn [nhiều] expr - expr. Vì NFlà một biểu thức chính nó, $NF-1nên đánh giá đến ($NF)-1. Ngay cả khi, sau khi tất cả, có thực sự awk triển khai trên mạng mà đánh giá $NF-1như $(NF-1), bài học học được ở đây là sử dụng $(NF-1)là sự lựa chọn an toàn và di động.
mklement0

0

thử với cái này

$ cat /tmp/topfs.txt
/dev/sda2      xfs        32G   10G   22G  32% /

awk print last column
$ cat /tmp/topfs.txt | awk '{print $NF}'

awk print before last column
$ cat /tmp/topfs.txt | awk '{print $(NF-1)}'
32%

awk - print last two columns
$ cat /tmp/topfs.txt | awk '{print $(NF-1), $NF}'
32% /

0

Vui lòng thử điều này để tính đến tất cả các trường hợp có thể xảy ra:

awk '{print $(NF-1)"\t"$NF}'  file

hoặc là

awk 'BEGIN{OFS="\t"}' file

hoặc là

awk '{print $(NF-1), $NF} {print $(NF-1), $NF}' file
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.