lặp lại awk {n} không hoạt động


18

Tôi đang cố gắng in các dòng bằng ký hiệu lặp lại {n} nhưng nó không hoạt động. Cho. ví dụ: tôi muốn in tất cả các dòng có chiều dài là 4 char

 awk '/^.{4}$/' test_data

Đoạn mã trên không in được. Làm thế nào để sửa nó để tôi có thể sử dụng ký hiệu lặp lại? Tôi biết cách thay thế như awk '/^....$/' test_dataawk 'length ==3 ' test_data


3
Bạn đang sử dụng bản phân phối nào? Mà nào?
terdon

1
$ awk --version GNU Awk 3.1.7 $ cat / etc / redhat phát hành Red Hat Enterprise Linux Server phát hành 6.7 (Santiago)
Người học mãi mãi

2
Tôi muốn nói awk '/^.{4}+$/{print}' <<<$'foods\nbaarsz\nfooo' là khớp đúng 4 ký tự. Cũng như bạn đã đề cập, awk 'length($0) == 4' test_datatương thích với hầu hết các awkphiên bản.
Valentin Bajrami

4
Làm awk --re-interval '/^.{4}$/' test_data hay awk --posix '/^.{4}$/' test_datalàm việc?
Steeldo

Cảm ơn bạn thép. Điều này đã giải quyết vấn đề của tôi. Nâng cao. Cảm ơn một lần nữa :)
Người học mãi mãi

Câu trả lời:


19

Theo Hướng dẫn sử dụng GNU Awk: Lịch sử tính năng , hỗ trợ cho các toán tử phạm vi biểu thức chính quy đã được thêm vào trong phiên bản 3.0 nhưng ban đầu yêu cầu tùy chọn dòng lệnh rõ ràng

Tùy chọn dòng lệnh mới:

  • Tùy chọn dòng lệnh mới:
    • Tùy chọn --lint-old để cảnh báo về các cấu trúc không có sẵn trong phiên bản Unix phiên bản 7 gốc của awk (xem V7 / SVR3.1).
    • Tùy chọn -m từ BWK awk. (Brian vẫn còn ở Phòng thí nghiệm Bell vào thời điểm đó.) Điều này sau đó đã bị xóa khỏi cả awk của anh ấy và từ gawk.
    • Tùy chọn --re-distance để cung cấp các biểu thức khoảng trong biểu thức chính quy (xem Toán tử khai thác).
    • Tùy chọn --trad điều kiện đã được thêm vào như một tên tốt hơn cho --compat (xem Tùy chọn).

Trong gawk4.0,

Biểu thức khoảng trở thành một phần của biểu thức chính quy mặc định

Vì bạn đang sử dụng gawk3.x, bạn sẽ cần sử dụng

awk --re-interval '/^.{4}$/'

hoặc là

awk --posix '/^.{4}$/'

hoặc (cảm ơn @ StéphaneChazelas) nếu bạn muốn một giải pháp có thể mang theo được, hãy sử dụng

POSIXLY_CORRECT=anything awk '/^.{4}$/'

(vì --posixhoặc --re-intervalsẽ gây ra lỗi trong các awktriển khai khác ).


Cảm ơn thép, đã dành thời gian và sự giúp đỡ của bạn. Được nâng cấp và chấp nhận như một câu trả lời
Người học mãi mãi

4
Tốt hơn là sử dụng POSIXLY_CORRECT=anything awk '/^.{4}/'vì điều đó làm cho mã di động (a --posixhoặc --re-intervalsẽ gây ra lỗi trong các awktriển khai khác ).
Stéphane Chazelas

Xin chào Stéphane Chazelas, khi tôi ban hành lệnh, $ POSIXLY_CORRECT = bất cứ điều gì awk '/ ^. Sau đó, tôi nhận ra rằng không có đồng đô la cuối cùng sau khi lặp lại. Cảm ơn cho đầu vào của bạn. Nâng cao nhận xét và giải pháp của bạn. Xin lỗi, tôi đã hiểu nhầm nó ngay từ đầu do bỏ sót $ sau khi lặp lại.
Học viên mãi mãi

20

ERE ( biểu thức chính quy mở rộng như được sử dụng bởi awkhoặc egrep) ban đầu không có {x,y}. Nó lần đầu tiên được giới thiệu trong BREs (như được sử dụng bởi grephoặc sed), nhưng với \{x,y\}cú pháp không phá vỡ tính di động lạc hậu.

Nhưng khi nó được thêm vào ERE với {x,y}cú pháp đó, nó đã phá vỡ tính di động lạc hậu vì foo{2}RE phù hợp với thứ gì đó khác trước đây.

Vì vậy, một số triển khai đã chọn không làm điều đó. Bạn sẽ thấy rằng /bin/awk, /bin/nawk/bin/egreptrên Solaris vẫn không tôn trọng nó (bạn cần sử dụng /usr/xpg4/bin/awkhoặc /usr/xpg4/bin/grep -E). Tương tự cho awknawktrên FreeBSD (dựa trên những awkđược duy trì bởi Brian Kernighan (các knăm awk)).

Đối với GNUawk , cho đến gần đây (phiên bản 4.0), bạn phải gọi POSIXLY_CORRECT=anything awk '/^.{4}$/'nó để tôn vinh nó. mawkvẫn không tôn vinh nó .

Lưu ý rằng toán tử chỉ là đường cú pháp. .{3,5}luôn luôn có thể được viết ....?.?ví dụ (mặc dù tất nhiên {3,5}là dễ đọc hơn rất nhiều, và tương đương (foo.{5,9}bar){123,456}sẽ tệ hơn rất nhiều).


Cảm ơn một lần nữa Stéphane Chazelas. Xin lỗi, xấu của tôi, tôi không thể hiểu câu trả lời của bạn ban đầu. Cảm ơn rất nhiều và nâng cao.
Học viên mãi mãi

6

Điều này hoạt động như mong đợi với GNU awk(gawk):

$ printf 'abcd\nabc\nabcde\n' | gawk '/^.{4}$/'
abcd

Nhưng thất bại với mawkPOSIX gần hơn awkvà, AFAIK, là mặc định trên các hệ thống Ubuntu:

$ printf 'abcd\nabc\nabcde\n' | mawk '/^.{4}$/'
$ ## prints nothing

Vì vậy, một giải pháp đơn giản sẽ là sử dụng gawkthay vì awk. Các {n}ký hiệu không phải là một phần của cú pháp POSIX BRE (biểu thức chính quy cơ bản). Đó là lý do tại sao grepcũng thất bại ở đây:

$ printf 'abcd\nabc\nabcde\n' | grep '^.{4}$'
$

Tuy nhiên, nó là một phần của ERE (biểu thức chính quy mở rộng):

$ printf 'abcd\nabc\nabcde\n' | grep -E '^.{4}$'
abcd

Tôi không biết hương vị regex nào được sử dụng bởi mawkhoặc POSIX awk, nhưng tôi đoán nó là BRE. Họ sử dụng phiên bản cũ hơn của ERE theo câu trả lời của Stéphane . Trong mọi trường hợp, rõ ràng là bạn đang sử dụng một phiên bản awkkhông triển khai ERE hoặc đầu vào của bạn không thực sự có bất kỳ dòng nào có đúng 4 ký tự. Điều này có thể xảy ra do khoảng trắng mà bạn không nhìn thấy hoặc unicode glyphs, ví dụ.


Xin chào terdon, tôi muốn in các dòng dài 4 ký tự. Không phải bốn ký tự đầu tiên của một dòng. '^ {4} $' Ví dụ $ grep -E test_data, sẽ làm việc nhưng cùng không hoạt động với awk
Mãi mãi Learner

@CppLearner vâng, đó là những gì tôi đang làm ở đây. Ý anh là gì?
terdon

@CppLearner, giải pháp của @ terdon chỉ in các dòng dài 4 ký tự. Nhưng nếu bạn thực sự chỉ quan tâm đến độ dài dòng, bạn chỉ nên sử dụng length($0)hiệu quả hơn regexes.
Stephen Kitt

Xin chào terdon, giải pháp của Steeldo là những gì tôi đang tìm kiếm. Cảm ơn vì đã dành thời gian cho tôi. Xin chào Stephen Kitt, Như tôi đã đề cập trong vấn đề này, tôi đã sử dụng độ dài thay thế, tôi quan tâm hơn đến việc tại sao regex lặp lại {n} không hoạt động từ nhận xét của Steeldo Tôi biết rằng tôi cần sử dụng tùy chọn --re-distance hoặc --poseix. Cảm ơn vì đã dành thời gian cho tôi.
Học viên mãi mãi

1
mawkkhông thực sự gần gũi hơn với POSIX awkvà không sử dụng BREs. Nó không sử dụng ERE nhưng không có {x,y}toán tử.
Stéphane Chazelas
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.