Một câu hỏi về awk


9

Ok, vì đây là một câu hỏi phức tạp, tôi sẽ giải thích rõ ràng. Tôi có một nội dung tập tin như dưới đây:

$ Cat File1 
ABC Cool Lol POP {MNB}
ABC Cool Lol POP {MNB}
ABC Cool Lol POP {MNB}
ABC Cool Lol POP {TBMKF}
ABC Cool Lol POP {YUKER}
ABC Cool Lol POP {EFEFVD}

Đầu ra mà tôi muốn

-Cool MNB +  POP ;
-Cool MNB  + POP ;
-Cool MNB  + POP ;
-Cool TBMKF + POP ;
-Cool YUKER + POP ;
-Cool EFEFVD +POP ;

Đầu tiên tôi cố gắng lấy ra cột cuối cùng từ File1và in ra sed 's/[{}//g' File1 > File3

Sau đó tôi sao chép toàn bộ nội dung File1sang một cái mớiFile4

cp File1 File4

Sau đó, tôi thay thế dữ liệu bên trong File4bằng File3dữ liệu (có nghĩa là dữ liệu không có khung một " File1cột cuối cùng đó")

awk 'FNR==NR{a[NR]=$1;next}{$5=a[FNR]}1' File3 File4 >>File5 

Đầu ra nên như thế này

ABC Cool Lol POP MNB
ABC Cool Lol POP MNB
ABC Cool Lol POP MNB
ABC Cool Lol POP TBMKF
ABC Cool Lol POP YUKER
ABC Cool Lol POP EFEFVD

Cuối cùng, tôi cố gắng

awk -F " '{print - $2,$5 +,$4 ";"}‘ File5

Nhưng kết quả đã không diễn ra như tôi muốn, chỉ có dữ liệu tương tự MNB được liệt kê xuống, những người khác không hiển thị (Tệp một dữ liệu cột cuối cùng),


Bạn đang sử dụng gnu awk?
123

Tôi không chắc ý của bạn là gì. Nhưng tôi chỉ là một người mới bắt đầu chạm vào awk. Đây là nhiệm vụ mà tôi cần phải làm, tôi cố gắng hết sức để từ từ một bước đến một bước để làm điều đó dựa trên sự hiểu biết của tôi về awk.
heng960407

1
loại awk --version, kết quả là gì?
123

2
Vui lòng thay đổi tiêu đề của bạn để một cái gì đó cụ thể hơn cho vấn đề của bạn. Điều này sẽ giúp những người khác có câu hỏi tương tự dễ dàng hơn trong tương lai tìm thấy nó. Hiện tại "Một câu hỏi về awk" rất chung chung.
Tom Fenech

Câu trả lời:


16

Tôi không biết tại sao bạn lại sao chép những thứ trái và phải. Điều đơn giản là

awk '{print "-" $2, substr($5,2,length($5)-2), "+", $4, ";"}' File1

Tôi đặt -vào đầu và ;cuối rồi.

Ở giữa chúng tôi in

  • $2 bởi vì chúng tôi muốn nó như nó là.
  • một chuỗi con của $5, đó là chuỗi không có ký tự đầu tiên và cuối cùng. Chúng tôi bỏ qua ký tự đầu tiên bằng cách bắt đầu ở vị trí 2 (awk luôn lạ về điều đó) và bỏ qua ký tự cuối cùng bằng cách chỉ chọn một chuỗi con ngắn hơn hai ký tự, so với bản gốc$5
  • các +vì chúng tôi muốn nó
  • và sau đó $4

Tuy nhiên, tôi không chắc liệu tất cả các hàm chuỗi này có dành riêng cho GNU awk hay không.


substr(string, 2)trả về chuỗi con bắt đầu từ nhân vật thứ hai, giống như cut -c2-, tail -n +2, sed '2,$'... Có gì đáng lạ về điều đó?
Stéphane Chazelas

3
Lệnh đó là tiêu chuẩn và thậm chí sẽ hoạt động với bản gốc awktừ những năm 70.
Stéphane Chazelas

@ StéphaneChazelas: Ah, tôi đã đợi bạn :-) Thông thường chúng tôi bắt đầu đếm ở 0 có nghĩa là chỉ số 2 là vị trí thứ ba, nhưng ở đây vị trí thứ hai là ở chỉ số 2. Cảm ơn bạn đã làm rõ câu hỏi GNU còn lại.
Bananguin

@Bananguin, trong shell Unix và các tiện ích như trong một vài ví dụ ở trên, chúng tôi bắt đầu từ 1, không phải 0. Các ngoại lệ đáng chú ý nhất là mảng ksh và $ {var: offset} (cả hai được sao chép bởi bash). Tất cả các mảng shell khác bắt đầu từ 1. Xem thêm Có lý do tại sao phần tử đầu tiên của mảng Zsh được lập chỉ mục bằng 1 thay vì 0 không?
Stéphane Chazelas

7

Với sed

sed '
    s/\S\+\s/-/
    s/\(\S\+\s\)\{2\}{\(\S\+\)}/\2 + \1;/
    ' File1

Và biến thể awk

awk -F"[[:blank:]{}]+" '{print "-" $2, $5, "+", $4}' ORS=" ;\n" File1

6

Công việc TXR dễ dàng :

$ txr -c '@(repeat)
@a @b @c @d {@e}
@(do (put-line `-@b @e + @d ;`))
@(end)' -
ABC Cool Lol POP {MNB}
ABC Cool Lol POP {MNB}
ABC Cool Lol POP {MNB}
ABC Cool Lol POP {TBMKF}
ABC Cool Lol POP {YUKER}
ABC Cool Lol POP {EFEFVD}
[Ctrl-D][Enter]
-Cool MNB + POP ;
-Cool MNB + POP ;
-Cool MNB + POP ;
-Cool TBMKF + POP ;
-Cool YUKER + POP ;
-Cool EFEFVD + POP ;

Sử dụng macro TXR Lisp awk để chuyển ngữ giải pháp Awk:

 txr -e '(awk (t (prn `-@[f 1] @{[f 4] [1..-1]} + @[f 3] ;`)))'

Các trường nằm trong fdanh sách và lập chỉ mục là không dựa trên.


1
+1 cho cái nhìn lisp và crytiest! Ngôn ngữ đó PHẢI cạnh tranh trong pcg (mã lập trình golf)
Archemar

@Archemar TXR không cạnh tranh trong việc chơi golf rất tốt bởi vì có những ngôn ngữ chuyên biệt được thiết kế để thực hiện những việc như gán chức năng cho từng nhân vật, sau đó có thể kết hợp với nhau để đạt được thành phần.
Kaz


1
@Kaz Có hướng dẫn TXR ở đâu đó không? Trang người đàn ông có vẻ khá lớn. Làm thế nào để nó thực hiện so với awk?
bli

1
@bli GNU Awk là một cái gì đó nhanh hơn ít nhất 30 lần khi phân tách trường cơ bản qua một tệp lớn hơn macro awk TXR, đó là hơn 220 dòng mã được giải thích , bao gồm cả vòng lặp chung để xử lý các nguồn đầu vào thành các bản ghi và trường.
Kaz

3

Sử dụng awk là dễ nhất khi các $1,$2,...trường đã chứa các chuỗi chính xác mà bạn muốn làm việc. Dấu tách trường, nếu nó chứa nhiều hơn một ký tự, được hiểu là một biểu thức chính quy. Chúng tôi không cần thực hiện bất kỳ thao tác tìm kiếm và thay thế hoặc chuỗi con nào để thoát khỏi {dấu ngoặc nhọn}. Chúng tôi chỉ tính chúng là một phần của dấu phân cách.

awk -F'[ {}]+' '{printf("-%s %s + %s ;\n", $2, $5, $4)}'

Sử dụng printfthay vì printcũng giúp dễ dàng hơn một chút để xem chuỗi sẽ được định dạng như thế nào, nhưng nếu bạn muốn có print "-"$2,$5" + "$4";"thay thế printf("-%s %s + %s ;\n", $2, $5, $4), đó là một tùy chọn.

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.