(grep) Regex để khớp các ký tự không phải ASCII?


169

Trên Linux, tôi có một thư mục chứa rất nhiều tệp. Một số trong số chúng có các ký tự không phải ASCII, nhưng chúng đều là UTF-8 hợp lệ . Một chương trình có một lỗi khiến nó không hoạt động với tên tệp không phải ASCII và tôi phải tìm hiểu xem có bao nhiêu bị ảnh hưởng. Tôi sẽ làm điều này với findvà sau đó thực hiện một grep để in các ký tự không phải ASCII, và sau đó làm một wc -lđể tìm số. Nó không phải là grep; Tôi có thể sử dụng bất kỳ biểu thức chính quy Unix tiêu chuẩn nào , như Perl , sed , AWK , v.v.

Tuy nhiên, có một biểu thức chính quy cho 'bất kỳ ký tự nào không phải là ký tự ASCII' không?


1
Paul, vâng, tôi có thể sử dụng perl
Rory

/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x9F]
Tinmarino

Câu trả lời:


310

Điều này sẽ khớp với một ký tự không phải ASCII:

[^\x00-\x7F]

Đây là một PCRE hợp lệ ( Biểu thức chính quy tương thích Perl ).

Bạn cũng có thể sử dụng các tốc ký POSIX :

  • [[:ascii:]] - khớp với một char ASCII duy nhất
  • [^[:ascii:]] - khớp với một char không phải ASCII

[^[:print:]] có lẽ sẽ đủ cho bạn. **


3
@adrianm: Không, ^có giá trị trong PCRE.
Alix Axel

10
Điều đó hoàn toàn chính xác. Tuy nhiên, bạn phải sử dụng pcregrep, không phải grep tiêu chuẩn. [^ [: print:]] sẽ không hoạt động nếu thiết bị đầu cuối của bạn được thiết lập trong UTF8.
Rory

@Rory, tại sao :print:không hoạt động trong thiết bị đầu cuối UTF8? Điều này hoạt động với tôi trong 27.chr =~ /[^[:print:]]/
pry

Điều này thực sự tốt cho việc sửa tên tệp xấu - rename 's/[^\x00-\x7F]//g' *(bạn có thể sử dụng -nđể kiểm tra tên đổi trước là ok).
ness101

Làm cách nào để khớp với bất kỳ ký tự nào không phải là UTF8 và bất kỳ ký tự cụ thể nào khác?
CMCDragonkai

37

Không, [^\x20-\x7E]không phải là ASCII.

Đây là ASCII thật:

 [^\x00-\x7F]

Mặt khác, nó sẽ cắt bớt các dòng mới và các ký tự đặc biệt khác là một phần của bảng ASCII!



3

[^\x00-\x7F][^[:ascii:]]bỏ lỡ một số byte điều khiển để đôi khi chuỗi có thể là tùy chọn tốt hơn. Ví dụ cat test.torrent | perl -pe 's/[^[:ascii:]]+/\n/g'sẽ làm những điều kỳ lạ cho thiết bị đầu cuối của bạn, nơi strings test.torrentsẽ hành xử.


3

Để xác thực hộp văn bản Chấp nhận Ascii Chỉ sử dụng mẫu này

[\x00-\x7F]+



2

Bạn có thể sử dụng regex này:

[^\w \xC0-\xFF]

Trường hợp hỏi, các tùy chọn là Multiline .


2

Bạn không thực sự cần một regex.

printf "%s\n" *[!\ -~]*

Điều này cũng sẽ hiển thị tên tệp với các ký tự điều khiển trong tên của chúng, nhưng tôi coi đó là một tính năng.

Nếu bạn không có bất kỳ tệp phù hợp nào, toàn cầu sẽ mở rộng thành chính nó, trừ khi bạn đã nullglobđặt. (Biểu thức không khớp với chính nó, vì vậy về mặt kỹ thuật, đầu ra này không rõ ràng.)


Một cách muộn màng, tôi có thể quan sát rằng đây không hoạt động chính xác nếu bạn thực sự có một số tác phẩm mà phù hợp với mô hình này. Hành vi mà mẫu in tự in khi không có kết quả trùng khớp là hơi đáng ngạc nhiên nhưng thực sự chính xác. Tôi chỉnh sửa câu trả lời để hy vọng làm rõ điều này.
tripleee

1

Điều này hóa ra là rất linh hoạt và mở rộng. $ trường = ~ s / [^ \ x00- \ x7F] // g; # do đó, tất cả các mục không phải ASCII hoặc các mục cụ thể trong câu hỏi có thể được làm sạch. Rất đẹp trong việc lựa chọn hoặc xử lý trước các mục cuối cùng sẽ trở thành khóa băm.

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.