Nếu bạn đủ điều kiện từ có nghĩa là bất kỳ chuỗi của 1 hoặc nhiều phi trống ký tự thì câu trả lời chắc chắn là có, và nó rất đơn giản được thực hiện là tốt. Điều này là do [[:blank:]]*
và [^[:blank:]]*
là bổ sung boolean và - miễn là tất cả các ký tự trong một chuỗi hoàn tất - [[:blank:]]*
U [^[:blank:]]*
có thể mô tả bất kỳ chuỗi nào có thể theo cách tương tự .*
.
Nếu một ký tự không đầy đủ hoặc chuỗi byte không hợp lệ tồn tại trong một chuỗi thì không thể mô tả thành công nó từ đầu đến cuối - như đôi khi có thể xảy ra khi diễn giải một chuỗi trong mã hóa sai. Để đảm bảo một ký tự hoàn chỉnh trên mỗi byte trong bất kỳ chuỗi nào, ngôn ngữ C có thể được buộc như sau:
LC_ALL=C sed ...
... sẽ tránh mọi vấn đề mô tả chuỗi từ đầu đến đuôi với một mẫu bao gồm tất cả, chẳng hạn như .*
hoặc([ ]*[^ ]*)*
Một mô hình bổ sung đầy đủ có thể lặp lại nhiều lần khi cần thiết từ trái sang phải độ dài của bất kỳ chuỗi nào để hạ cánh ở lần xuất hiện cuối cùng mà không có bất kỳ sự phá vỡ nào trong mẫu. Đây là, chắc chắn, ngôn ngữ thường xuyên.
BRE:
sed 's/\(\([^[:blank:]]*\)[[:blank:]]*\)*/\2/'
ERE:
sed -E 's/(([^[:blank:]]*)[[:blank:]]*)*/\2/'
Cả hai phiên bản này vẫn sẽ in các dòng trống và điều này là do *
ngôi sao Kleene khớp với 0 hoặc nhiều lần xuất hiện của một mẫu. Đầu tiên, nó khớp với 0 hoặc nhiều hơn các ký tự trống, sau đó là 0 hoặc nhiều ký tự trống, sau đó là 0 hoặc nhiều lần xuất hiện của các kết quả khớp nhóm cho đến khi nó khớp toàn bộ chuỗi.
Đã khớp với tất cả những điều này, phép màu xảy ra trong sự thay thế - các tham chiếu được trả về bởi các nhóm \1
và \2
là lần xuất hiện cuối cùng của mỗi nhóm. Vì vậy, khi thay thế được thực hiện, tất cả các chuỗi được thay thế chỉ với lần xuất hiện cuối cùng trên một dòng bằng 0 hoặc nhiều hơn các ký tự trống - hoặc nhóm con \2
.
Tất nhiên, điều này hoạt động cho bất kỳ chuỗi nào có thể - ngay cả một chuỗi trống - có nghĩa là cả hai biểu mẫu sẽ in các ký tự dòng mới cho các dòng chỉ chứa các ký tự trống hoặc không có ký tự nào cả. Để xử lý việc này, có một vài điều bạn có thể làm, nhưng trước tiên hãy làm cho lớp nhân vật dễ nhập hơn một chút:
b='[:blank:]'
Bây giờ, chỉ in nếu một dòng chứa một hoặc nhiều ký tự trống bạn có thể làm:
BRE:
sed -n "s/\(\([^$b]*\)[$b]*\)*/\2/;/./p"
ERE:
sed -En "/[^$b]/s/(([^$b]*)[$b]*)*/\2/p"
- Trường hợp BRE - sự thay thế luôn được thực hiện và chỉ các không gian mẫu có ít nhất một ký tự còn lại được in.
- Trường hợp ERE - sự thay thế chỉ được thử trên một không gian mẫu có chứa ít nhất một char không trống.
Một trong hai hình thức sẽ hoạt động với một trong hai phương thức - miễn là cú pháp đúng.
Công -n
tắc vô hiệu hóa tự động in không gian mẫu và p
cờ vào s///
ubstlation hoặc các lệnh /
địa chỉ chỉ /
in kết quả của nó nếu thành công.
Logic tương tự này cũng có thể được áp dụng để có được bất kỳ {num}
sự xuất hiện nào, như, như:
BRE:
sed -n "s/\([$b]*\([^$b]\{1,\}\)\)\{num\}.*/\2/p"
ERE:
sed -En "s/([$b]*([^$b]+)){num}.*/\2/p"
... Trong đó num
cả hai biểu thức chính có thể được thay thế bằng một số để chỉ in {num}
lần xuất hiện được chỉ định của một chuỗi các ký tự không trống. Một hình thức hơi khác nhau được sử dụng ở đây để đảm bảo số lượng không bị sai lệch cho không gian hàng đầu trong một chuỗi.
Lưu ý rằng -E
ERE chuyển sang sed
được hỗ trợ trong cả BSD và các phiên bản GNU, mặc dù nó không phải là chưa POSIX cú pháp chuẩn.
sed
không?