Bạn có thể thực hiện các cách tiếp cận khác nhau tùy thuộc vào việc awk
xử lý RS
như một ký tự đơn lẻ (như cách awk
triển khai truyền thống ) hoặc như một biểu thức thông thường (thích gawk
hoặc mawk
làm). Các tập tin trống cũng rất khó để được coi là awk
có xu hướng bỏ qua chúng.
gawk
, mawk
Hoặc khác awk
triển khai ở đâu RS
có thể là một biểu thức chính quy.
Trong các triển khai đó (đối với mawk
, hãy cẩn thận rằng một số HĐH như Debian gửi phiên bản rất cũ thay vì phiên bản hiện đại được duy trì bởi @ThomasDickey ), nếu RS
chứa một ký tự, dấu tách bản ghi là ký tự đó hoặc awk
vào chế độ đoạn khi RS
trống, hoặc coi RS
như một biểu thức thông thường khác.
Giải pháp là sử dụng một biểu thức chính quy không thể phù hợp. Một số đến với tâm trí như x^
hoặc $x
( x
trước khi bắt đầu, hoặc sau khi kết thúc). Tuy nhiên, một số (đặc biệt với gawk
) đắt hơn những cái khác. Cho đến nay, tôi đã thấy rằng đó ^$
là một cách hiệu quả nhất. Nó chỉ có thể khớp với đầu vào trống, nhưng sau đó sẽ không có gì phù hợp.
Vì vậy, chúng ta có thể làm:
awk -v RS='^$' '{printf "%s: <%s>\n", FILENAME, $0}' file1 file2...
Một điều lưu ý là nó bỏ qua các tập tin trống (trái với perl -0777 -n
). Điều đó có thể được giải quyết với GNU awk
bằng cách đặt mã trong một ENDFILE
câu lệnh thay thế. Nhưng chúng ta cũng cần đặt lại $0
trong câu lệnh BEGINFILE vì nếu không nó sẽ không được đặt lại sau khi xử lý tệp trống:
gawk -v RS='^$' '
BEGINFILE{$0 = ""}
ENDFILE{printf "%s: <%s>\n", FILENAME, $0}' file1 file2...
awk
triển khai truyền thống , POSIXawk
Trong đó, RS
chỉ là một ký tự, họ không có BEGINFILE
/ ENDFILE
, họ không có RT
biến, họ thường không thể xử lý ký tự NUL.
Bạn sẽ nghĩ rằng việc sử dụng RS='\0'
có thể hoạt động sau đó vì dù sao họ không thể xử lý đầu vào có chứa byte NUL, nhưng không, RS='\0'
trong các triển khai truyền thống được coi RS=
là chế độ đoạn văn.
Một giải pháp có thể là sử dụng một ký tự không chắc chắn được tìm thấy trong đầu vào như thế nào \1
. Trong các địa điểm ký tự đa nhân, bạn thậm chí có thể tạo ra các chuỗi byte rất khó xảy ra khi chúng tạo thành các ký tự không được gán hoặc không phải ký tự như $'\U10FFFE'
trong các địa phương UTF-8. Mặc dù không thực sự hoàn hảo và bạn cũng gặp vấn đề với các tập tin trống.
Một giải pháp khác có thể là lưu trữ toàn bộ đầu vào trong một biến và xử lý nó trong câu lệnh END ở cuối. Điều đó có nghĩa là bạn chỉ có thể xử lý một tệp tại một thời điểm:
awk '{content = content $0 RS}
END{$0 = content
printf "%s: <%s>\n", FILENAME, $0
}' file
Đó là tương đương với sed
:
sed '
:1
$!{
N;b1
}
...' file1
Một vấn đề khác với cách tiếp cận đó là nếu tệp không kết thúc bằng ký tự dòng mới (và không trống), $0
thì cuối cùng vẫn được thêm vào một cách tùy tiện (với gawk
, bạn sẽ xử lý xung quanh bằng cách sử dụng RT
thay vì RS
trong mã ở trên). Một lợi thế là bạn có bản ghi số lượng dòng trong tệp trong NR
/ FNR
.