ฉันจะ grep สำหรับอักขระที่ไม่ใช่ ASCII ทั้งหมดได้อย่างไร


359

ฉันมีไฟล์ XML ที่มีขนาดใหญ่มากและฉันพยายามค้นหาบรรทัดที่มีอักขระที่ไม่ใช่ ASCII ฉันได้ลองทำสิ่งต่อไปนี้แล้ว:

grep -e "[\x{00FF}-\x{FFFF}]" file.xml

แต่สิ่งนี้จะคืนค่าทุกบรรทัดในไฟล์โดยไม่คำนึงว่าบรรทัดนั้นมีอักขระในช่วงที่ระบุหรือไม่

ฉันมีไวยากรณ์ผิดหรือฉันทำอย่างอื่นผิดปกติหรือไม่? ฉันยังลอง:

egrep "[\x{00FF}-\x{FFFF}]" file.xml 

(ด้วยเครื่องหมายคำพูดเดี่ยวและคู่ล้อมรอบรูปแบบ)


อักขระ ASCII มีความยาวเพียงหนึ่งไบต์ดังนั้นหากไฟล์เป็น Unicode ไม่ควรมีอักขระเกิน 0xFF
— zdav

เราไปเหนือ \ xFF อย่างไร ข้อผิดพลาด Grep ให้ข้อผิดพลาด "grep: ช่วงของการสั่งซื้อในคลาสตัวละคร"
— Mudit Jain

คำตอบ:


494

คุณสามารถใช้คำสั่ง:

grep --color='auto' -P -n "[\x80-\xFF]" file.xml

นี่จะทำให้คุณมีหมายเลขบรรทัดและจะเน้นตัวอักษรที่ไม่ใช่ ASCII เป็นสีแดง

ในบางระบบขึ้นอยู่กับการตั้งค่าของคุณข้อมูลด้านบนจะไม่ทำงานดังนั้นคุณสามารถกดผกผันได้

grep --color='auto' -P -n "[^\x00-\x7F]" file.xml

โปรดทราบว่าบิตที่สำคัญคือ-Pธงซึ่งเท่ากับ--perl-regexp: ดังนั้นมันจะตีความรูปแบบของคุณเป็นนิพจน์ปกติของ Perl มันก็บอกว่า

นี่คือการทดลองอย่างมากและ grep -P อาจเตือนถึงคุณลักษณะที่ยังไม่ได้ใช้งาน


42
สิ่งนี้จะไม่ทำงานใน BSD grep(บน OS X 10.8 Mountain Lion) เนื่องจากไม่รองรับPตัวเลือก
— Bastiaan M. van de Weerd

20
เพื่ออัปเดตความคิดเห็นล่าสุดของฉันรุ่น GNU grepมีอยู่ในdupesห้องสมุดของ Homebrew (เปิดใช้งานโดยใช้brew tap homebrew/dupes):brew install grep
— Bastiaan M. van de Weerd

48
@BastiaanVanDeWeerd ถูกต้อง grep บน OSX 10.8 ไม่รองรับ PCRE ("นิพจน์ทั่วไปที่เข้ากันได้กับ Perl") เนื่องจากดาร์วินใช้ grep BSD แทน grep GNU อีกทางเลือกหนึ่งในการติดตั้งdupesไลบรารีคือการติดตั้งpcreแทน: brew install pcre... ซึ่งเป็นส่วนหนึ่งของสิ่งนี้คุณจะได้รับpcregrepยูทิลิตี้ซึ่งคุณสามารถใช้ดังนี้:pcregrep --color='auto' -n "[\x80-\xFF]" file.xml
— pvandenberk

15
สำหรับ Mac brewผู้ใช้coreutils GNU ของbrew install coreutilsสามารถติดตั้งได้กับ ซึ่งจะทำให้คุณจำนวนมากเครื่องมือ GNU นำหน้าด้วย 'g' - ggrepในกรณีนี้การใช้งาน สิ่งนี้ควรหลีกเลี่ยงปัญหาที่เกิดขึ้นจากการแทนที่ยูทิลิตี้ระบบเนื่องจากสคริปต์ Mac เฉพาะระบบขึ้นอยู่กับ grep BSD
— Joel Purra

22
ทำงานได้ดีบน mac ที่ag "[\x80-\xFF]" fileคุณต้องติดตั้งthe_silver_searcher
— slf

123

แทนที่จะทำการตั้งสมมติฐานเกี่ยวกับช่วงไบต์ของอักขระที่ไม่ใช่ ASCII เนื่องจากวิธีแก้ไขปัญหาข้างต้นส่วนใหญ่จะเป็นการดีกว่าเล็กน้อยที่ IMO จะมีความชัดเจนเกี่ยวกับช่วงไบต์ที่แท้จริงของอักขระ ASCII แทน

ดังนั้นทางออกแรกเช่นจะกลายเป็น:

grep --color='auto' -P -n '[^\x00-\x7F]' file.xml

(ซึ่งโดยทั่วไปแล้ว greps สำหรับตัวละครใด ๆ ที่อยู่นอกช่วง ASCII เลขฐานสิบหก: จาก \ x00 ถึง \ x7F)

บน Mountain Lion ที่ไม่ทำงาน(เนื่องจากขาดการสนับสนุน PCRE ใน grep BSD)แต่ด้วยการpcreติดตั้งผ่าน Homebrew ต่อไปนี้จะทำงานได้เช่นกัน:

pcregrep --color='auto' -n '[^\x00-\x7F]' file.xml

ข้อดีหรือข้อเสียใด ๆ ที่ใคร ๆ ก็คิดได้


9
มันใช้งานได้จริงสำหรับฉันที่การแก้ปัญหาข้างต้นล้มเหลว การค้นหาอะโพสโทรฟี M $ Word นั้นไม่ใช่เรื่องง่าย!
— AlbertEngelB

2
หากคุณมี bash-shell ที่เข้ากันได้ แต่ไม่ทำงาน pcre-grep ให้LC_COLLATE=C grep $'[^\1-\177]'ทำงาน (สำหรับไฟล์ที่ไม่มีไบต์ว่าง)
— idupree

2
วิธีนี้ดูเหมือนว่าจะทำงานได้อย่างต่อเนื่องมากกว่าที่กล่าวไว้ข้างต้น
— 0xcaff

1
ฉันต้องใช้มันเพื่อรับคันจิซิริลลิกและจีนดั้งเดิมในไฟล์ UTF8 ของฉันโดยใช้ "[\ x80- \ xFF]" พลาดสิ่งเหล่านี้ทั้งหมด
— buckaroo1177125

1
โปรนี้ใช้งานได้ดีในขณะที่ตัวเลือกอื่น ๆ นั้นยอดเยี่ยม แต่ไม่ยอดเยี่ยม ไม่พบข้อเสีย
— jwpfox

67

งานต่อไปนี้สำหรับฉัน:

grep -P "[\x80-\xFF]" file.xml

อักขระที่ไม่ใช่ ASCII เริ่มต้นที่ 0x80 และไปที่ 0xFF เมื่อดูที่ไบต์ Grep (และตระกูล) ไม่ได้ทำการประมวลผล Unicode เพื่อรวมอักขระหลายไบต์เป็นเอนทิตีเดียวสำหรับการจับคู่ regex ตามที่คุณต้องการ -Pตัวเลือกใน grep ของฉันช่วยให้การใช้งานของ\xddหนีในชั้นเรียนตัวอักษรเพื่อให้บรรลุสิ่งที่คุณต้องการ


1
สำหรับมุมมองที่อาจไม่รู้วิธีเรียกสิ่งนี้ในหลาย ๆ ไฟล์ในทันทีให้เรียกใช้: ค้นหา -name * .xml | xargs grep -P "[\ x80- \ xFF]"
— David Mohundro

1
สิ่งนี้จะส่งคืนการแข่งขัน แต่ไม่มีข้อบ่งชี้ว่าตัวละครคืออะไรและอยู่ที่ไหน เราจะเห็นว่าตัวละครเป็นอย่างไรและอยู่ที่ไหน?
— Faheem Mitha

การเพิ่ม "-n" จะให้หมายเลขบรรทัดนอกจากนี้ตัวอักษรที่มองไม่เห็นจะแสดงเป็นบล็อกที่เทอร์มินัล: grep -n -P "[\ x80- \ xFF]" file.xml
— fooMonster

4
ฉันมีปัญหากับอังกูลเกาหลี: echo '소녀시대' | grep -P "[\x80-\xFF]"ไม่ส่งคืนสิ่งใดเลย - คนอื่นจะยืนยันได้ไหม (GNU grep 2.21)
— frabjous

@frabjous กันที่นี่ แต่ grepping echo '소녀시대' | grep -P "[^\x00-\x7F]"ผลงานผกผัน: หรือเพียงใช้the_silver_searcherตามที่ระบุโดย @slf:echo '소녀시대' | ag "[\x80-\xFF]"
— psmith

55

ใน Perl

perl -ane '{ if(m/[[:^ascii:]]/) { print  } }' fileName > newFile

1
ใน OSX10.11 ฉันต้องลอง grep + regex solution ก่อนที่จะค้นหาสิ่งนี้ซึ่งใช้งานได้จริง
— sg

สนใจที่จะแบ่งปันโซลูชัน OSX ที่ @sg ?!
— geotheory

สคริปต์ perl ด้านบนเป็นคำตอบที่ฉันกำลังพูดถึง
— sg

5
perl -lne 'print if /[^[:ascii:]]/' file.xml
— Naveed

43

วิธีง่ายๆคือการกำหนดอักขระที่ไม่ใช่ ASCII ... เป็นอักขระที่ไม่ใช่อักขระ ASCII

LC_ALL=C grep '[^ -~]' file.xml

เพิ่มแท็บหลังจาก^ถ้าจำเป็น

การตั้งค่าLC_COLLATE=Cหลีกเลี่ยงความผิดที่น่ารังเกียจเกี่ยวกับความหมายของช่วงตัวละครในภาษาต่างๆ การตั้งค่าLC_CTYPE=Cจำเป็นต้องจับคู่อักขระไบต์เดียวมิฉะนั้นคำสั่งจะพลาดลำดับไบต์ที่ไม่ถูกต้องในการเข้ารหัสปัจจุบัน LC_ALL=Cหลีกเลี่ยงการตั้งค่าเอฟเฟ็กต์ที่ขึ้นกับสถานที่ทั้งหมด


ใน RedHat 6.4 ด้วย tcsh ฉันต้องใช้ <<< env LC_COLLATE = C grep -n '[^ - ~]' file.xml >>> ฉันเพิ่ม -n เพื่อรับหมายเลขบรรทัด
— ddevienne

สำหรับฉันecho "A" | LC_COLLATE=C grep '[^ -~]'กลับมาแข่งขัน
— frabjous

1
@ frabjous หากคุณมีLC_ALL=en_US.UTF-8นั่นสำคัญกว่าการLC_COLLATEตั้งค่า คุณไม่ควรมีสิ่งนี้ในสภาพแวดล้อมของคุณ! เป็นเพียงการที่จะบังคับให้งานที่เฉพาะเจาะจงที่จะใช้สถานที่เกิดเหตุโดยเฉพาะอย่างยิ่งมักจะLC_ALL ในการตั้งสถานที่เริ่มต้นสำหรับทุกประเภทชุดC LANG
— Gilles 'หยุดความชั่วร้าย'

1
ตอนแรกฉันไม่ได้เพิ่มLC_ALL=Cมันทำงานแตกต่างกันใน Mac OS X และ Ubuntu หลังจากที่ฉันเพิ่มการตั้งค่านี้พวกเขาให้ผลลัพธ์เดียวกัน
— Max Peng

1
ใช้งานได้กับ Mac ในขณะที่โซลูชัน grep-based อื่นไม่ทำงาน
— Matthias Fripp

26

นี่คือตัวแปรอื่นที่ฉันพบว่าให้ผลลัพธ์ที่แตกต่างอย่างสิ้นเชิงจากการค้นหา grep [\x80-\xFF]ในคำตอบที่ยอมรับ อาจเป็นประโยชน์กับบางคนในการค้นหาอักขระที่ไม่ใช่ ASCII เพิ่มเติม:

grep --color='auto' -P -n "[^[:ascii:]]" myfile.txt

หมายเหตุ: grep ของคอมพิวเตอร์ของฉัน (Mac) ไม่ได้มี-Pตัวเลือกเพื่อให้ฉันไม่brew install grepและเริ่มเรียกร้องข้างต้นด้วยแทนggrepgrep


2
นี่เป็นคำตอบที่ดีที่สุดเพราะใช้งานได้ดีกับ Mac และ Linux
— tommy.carstensen

หนึ่งเดียวที่ทำงานสำหรับฉันบน Linux

9

รหัสต่อไปนี้ใช้งานได้:

find /tmp | perl -ne 'print if /[^[:ascii:]]/'

แทนที่/tmpด้วยชื่อของไดเรกทอรีที่คุณต้องการค้นหา


2
บน Mac ใช้งานได้ในขณะที่ grep-based ส่วนใหญ่ไม่ทำงาน
— Matthias Fripp

9

การค้นหาตัวอักษรที่พิมพ์ไม่ได้ TLDR; บทสรุปผู้บริหาร

  1. ค้นหาตัวควบคุมและขยาย unicode
  2. การตั้งค่าโลแคลเช่นLC_ALL=Cจำเป็นเพื่อให้ grep ทำในสิ่งที่คุณคาดหวังด้วย Unicode ที่ขยาย

ดังนั้นผู้ค้นหาถ่านที่ไม่ใช่ ASCII ที่ต้องการ:

$ perl -ne 'print "$. $_" if m/[\x00-\x08\x0E-\x1F\x80-\xFF]/' notes_unicode_emoji_test

เช่นเดียวกับในคำตอบด้านบน grep ผกผัน:

$ grep --color='auto' -P -n "[^\x00-\x7F]" notes_unicode_emoji_test

ในคำตอบสูงสุด แต่ด้วยLC_ALL=C:

$ LC_ALL=C grep --color='auto' -P -n "[\x80-\xFF]" notes_unicode_emoji_test

. . มากกว่า . . ระทมทุกข์รายละเอียดเกี่ยวกับเรื่องนี้:. . .

ฉันเห็นด้วยกับฮาร์วีย์ข้างต้นถูกฝังอยู่ในความคิดเห็นมักจะมีประโยชน์มากกว่าในการค้นหาอักขระที่ไม่สามารถพิมพ์ได้หรือเป็นเรื่องง่ายที่จะคิดว่าไม่ใช่ ASCII เมื่อคุณควรคิดถึงการพิมพ์ที่ไม่สามารถพิมพ์ได้ ฮาร์วีย์แนะนำ "ใช้สิ่งนี้:" [^\n -~]"เพิ่ม \ r สำหรับไฟล์ข้อความ DOS ซึ่งแปลเป็น"[^\x0A\x020-\x07E] "และเพิ่ม \ x0D สำหรับ CR"

นอกจากนี้การเพิ่ม -c (แสดงจำนวนรูปแบบที่ตรงกัน) ลงใน grep จะเป็นประโยชน์เมื่อค้นหา chars ที่ไม่สามารถพิมพ์ได้เนื่องจากสตริงที่จับคู่สามารถทำให้เทอร์มินัลหมด

ฉันพบการเพิ่มช่วง 0-8 และ 0x0e-0x1f (ในช่วง 0x80-0xff) เป็นรูปแบบที่มีประโยชน์ สิ่งนี้ไม่รวม TAB, CR และ LF และหนึ่งหรือสองตัวอักษรที่พิมพ์ผิดปกติได้ ดังนั้น IMHO รูปแบบ grep ที่ค่อนข้างมีประโยชน์ (แม้ว่าจะเป็นน้ำมันดิบ) ก็คืออันนี้:

grep -c -P -n "[\x00-\x08\x0E-\x1F\x80-\xFF]" *

ตามจริงแล้วโดยทั่วไปคุณจะต้องทำสิ่งนี้:

LC_ALL=C grep -c -P -n "[\x00-\x08\x0E-\x1F\x80-\xFF]" *

ทำให้พังถล่ม:

LC_ALL=C - set locale to C, otherwise many extended chars will not match (even though they look like they are encoded > 0x80)
\x00-\x08 - non-printable control chars 0 - 7 decimal
\x0E-\x1F - more non-printable control chars 14 - 31 decimal
\x80-1xFF - non-printable chars > 128 decimal
-c - print count of matching lines instead of lines
-P - perl style regexps

Instead of -c you may prefer to use -n (and optionally -b) or -l
-n, --line-number
-b, --byte-offset
-l, --files-with-matches

เช่นตัวอย่างการใช้งานจริงพบเพื่อ grep ไฟล์ทั้งหมดภายใต้ไดเรกทอรีปัจจุบัน:

LC_ALL=C find . -type f -exec grep -c -P -n "[\x00-\x08\x0E-\x1F\x80-\xFF]" {} + 

คุณอาจต้องการที่จะปรับ grep ในบางครั้ง เช่น BS (0x08 - backspace) ถ่านที่ใช้ในไฟล์ที่พิมพ์ได้บางส่วนหรือเพื่อยกเว้น VT (0x0B - แท็บแนวตั้ง) ตัวอักษร BEL (0x07) และ ESC (0x1B) นั้นสามารถพิมพ์ได้ในบางกรณี

Non-Printable ASCII Chars
** marks PRINTABLE but CONTROL chars that is useful to exclude sometimes
Dec   Hex Ctrl Char description           Dec Hex Ctrl Char description
0     00  ^@  NULL                        16  10  ^P  DATA LINK ESCAPE (DLE)
1     01  ^A  START OF HEADING (SOH)      17  11  ^Q  DEVICE CONTROL 1 (DC1)
2     02  ^B  START OF TEXT (STX)         18  12  ^R  DEVICE CONTROL 2 (DC2)
3     03  ^C  END OF TEXT (ETX)           19  13  ^S  DEVICE CONTROL 3 (DC3)
4     04  ^D  END OF TRANSMISSION (EOT)   20  14  ^T  DEVICE CONTROL 4 (DC4)
5     05  ^E  END OF QUERY (ENQ)          21  15  ^U  NEGATIVE ACKNOWLEDGEMENT (NAK)
6     06  ^F  ACKNOWLEDGE (ACK)           22  16  ^V  SYNCHRONIZE (SYN)
7     07  ^G  BEEP (BEL)                  23  17  ^W  END OF TRANSMISSION BLOCK (ETB)
8     08  ^H  BACKSPACE (BS)**            24  18  ^X  CANCEL (CAN)
9     09  ^I  HORIZONTAL TAB (HT)**       25  19  ^Y  END OF MEDIUM (EM)
10    0A  ^J  LINE FEED (LF)**            26  1A  ^Z  SUBSTITUTE (SUB)
11    0B  ^K  VERTICAL TAB (VT)**         27  1B  ^[  ESCAPE (ESC)
12    0C  ^L  FF (FORM FEED)**            28  1C  ^\  FILE SEPARATOR (FS) RIGHT ARROW
13    0D  ^M  CR (CARRIAGE RETURN)**      29  1D  ^]  GROUP SEPARATOR (GS) LEFT ARROW
14    0E  ^N  SO (SHIFT OUT)              30  1E  ^^  RECORD SEPARATOR (RS) UP ARROW
15    0F  ^O  SI (SHIFT IN)               31  1F  ^_  UNIT SEPARATOR (US) DOWN ARROW

UPDATE:ฉันต้องกลับมาทบทวนเรื่องนี้เมื่อเร็ว ๆ นี้ และ YYMV ขึ้นอยู่กับการตั้งค่าเทอร์มินัล / พยากรณ์อากาศแสงอาทิตย์ แต่ . ฉันสังเกตเห็นว่าgrep ไม่พบยูนิโค้ดหรือตัวละครมากมาย แม้ว่าพวกเขาควรจับคู่ช่วง 0x80 ถึง 0xff, 3 และ 4 ไบต์อักขระ unicode ไม่ตรงกัน ??? มีใครอธิบายเรื่องนี้ได้บ้าง ใช่. @frabjous ถามแล้ว @calandoa อธิบายว่าLC_ALL=Cควรใช้เพื่อตั้งค่าภาษาสำหรับคำสั่งเพื่อทำการจับคู่ grep

เช่นสถานที่ของฉันLC_ALL=ว่างเปล่า

$ locale
LANG=en_IE.UTF-8
LC_CTYPE="en_IE.UTF-8"
.
.
LC_ALL=

grep ที่มีค่าLC_ALL=ว่างตรงกับตัวอักษรเข้ารหัส 2 ไบต์ แต่ไม่เข้ารหัส 3 และ 4 ไบต์:

$ grep -P -n "[\x00-\x08\x0E-\x1F\x80-\xFF]" notes_unicode_emoji_test
5:© copyright c2a9
7:call  underscore c2a0
9:CTRL
31:5 © copyright
32:7 call  underscore

grep with LC_ALL=Cดูเหมือนจะไม่ตรงกับอักขระส่วนขยายทั้งหมดที่คุณต้องการ:

$ LC_ALL=C grep --color='auto' -P -n "[\x80-\xFF]" notes_unicode_emoji_test  
1:���� unicode dashes e28090
3:��� Heart With Arrow Emoji - Emojipedia == UTF8? f09f9298
5:� copyright c2a9
7:call� underscore c2a0
11:LIVE��E! ���������� ���� ���������� ���� �� �� ���� ����  YEOW, mix of japanese and chars from other e38182 e38184 . . e0a487
29:1 ���� unicode dashes
30:3 ��� Heart With Arrow Emoji - Emojipedia == UTF8 e28090
31:5 � copyright
32:7 call� underscore
33:11 LIVE��E! ���������� ���� ���������� ���� �� �� ���� ����  YEOW, mix of japanese and chars from other
34:52 LIVE��E! ���������� ���� ���������� ���� �� �� ���� ����  YEOW, mix of japanese and chars from other
81:LIVE��E! ���������� ���� ���������� ���� �� �� ���� ����  YEOW, mix of japanese and chars from other

การจับคู่ Perl นี้ (พบบางส่วนที่อื่นใน stackoverflow) หรือ grep ผกผันของคำตอบด้านบนดูเหมือนจะพบอักขระ ~ แปลกและ ~ วิเศษ ~ ~ ไม่ใช่ ASCII ทั้งหมดโดยไม่ต้องตั้งค่าภาษา:

$ grep --color='auto' -P -n "[^\x00-\x7F]" notes_unicode_emoji_test

$ perl -ne 'print "$. $_" if m/[\x00-\x08\x0E-\x1F\x80-\xFF]/' notes_unicode_emoji_test  

1 ‐‐ unicode dashes e28090
3 💘 Heart With Arrow Emoji - Emojipedia == UTF8? f09f9298
5 © copyright c2a9
7 call  underscore c2a0
9 CTRL-H CHARS URK URK URK 
11 LIVE‐E! あいうえお かが アイウエオ カガ ᚊ ᚋ ซฌ आइ  YEOW, mix of japanese and chars from other e38182 e38184 . . e0a487
29 1 ‐‐ unicode dashes
30 3 💘 Heart With Arrow Emoji - Emojipedia == UTF8 e28090
31 5 © copyright
32 7 call  underscore
33 11 LIVE‐E! あいうえお かが アイウエオ カガ ᚊ ᚋ ซฌ आइ  YEOW, mix of japanese and chars from other
34 52 LIVE‐E! あいうえお かが アイウエオ カガ ᚊ ᚋ ซฌ आइ  YEOW, mix of japanese and chars from other
73 LIVE‐E! あいうえお かが アイウエオ カガ ᚊ ᚋ ซฌ आइ  YEOW, mix of japanese and chars from other

ดังนั้นผู้ค้นหาถ่านที่ไม่ใช่ ASCII ที่ต้องการ:

$ perl -ne 'print "$. $_" if m/[\x00-\x08\x0E-\x1F\x80-\xFF]/' notes_unicode_emoji_test

เช่นเดียวกับในคำตอบด้านบน grep ผกผัน:

$ grep --color='auto' -P -n "[^\x00-\x7F]" notes_unicode_emoji_test

ในคำตอบสูงสุด แต่ด้วยLC_ALL=C:

$ LC_ALL=C grep --color='auto' -P -n "[\x80-\xFF]" notes_unicode_emoji_test

1
ตอบว่าทำไม grep ไม่ตรงกับอักขระที่เข้ารหัสในขนาดมากกว่า 2 ไบต์เนื่องจาก @calandoa และ frabjous ในความคิดเห็นด้านบนของคำถาม ใช้ LC_ALL = C ก่อนคำสั่ง grep
— gaoithe

1
ขอบคุณมากที่รบกวนโพสต์คำตอบที่ฝังไว้ภายใต้ upvotes 800 รายการ! ปัญหาของฉันคือตัวอักษร 0x02 คุณอาจต้องการวาง "ตัวอย่างการใช้งานจริง" ไว้ด้านบนเนื่องจากคุณไม่จำเป็นต้องอ่านโพสต์ทั้งหมดเพื่อดูว่าเป็นปัญหาของคุณหรือไม่
— Noumenon

1
ฉันรู้ว่าคำตอบที่เก่ามากและรายละเอียดที่น่าตื่นเต้น แต่ก็มีประโยชน์สำหรับฉันและผู้อื่นเช่นกัน คุณพูดถูกฉันเพิ่ม TLDR ที่ด้านบน
— gaoithe

1

น่าแปลกที่ฉันต้องทำวันนี้! ฉันลงเอยด้วยการใช้ Perl เพราะฉันไม่สามารถรับ grep / egrep ให้ทำงานได้ (แม้ในโหมด -P) สิ่งที่ต้องการ:

cat blah | perl -en '/\xCA\xFE\xBA\xBE/ && print "found"'

สำหรับอักขระ Unicode (เช่น\u2212ในตัวอย่างด้านล่าง) ใช้สิ่งนี้:

find . ... -exec perl -CA -e '$ARGV = @ARGV[0]; open IN, $ARGV; binmode(IN, ":utf8"); binmode(STDOUT, ":utf8"); while (<IN>) { next unless /\N{U+2212}/; print "$ARGV: $&: $_"; exit }' '{}' \;

1

อาจเป็นเรื่องที่น่าสนใจที่จะทราบวิธีค้นหาอักขระ Unicode หนึ่งตัว คำสั่งนี้สามารถช่วยได้ คุณจะต้องรู้รหัสใน UTF8 เท่านั้น

grep -v $'\u200d'

ฉันไม่ใช่ผู้เชี่ยวชาญจริงๆ แต่ฉันรู้พอที่จะรู้ว่านั่นไม่ใช่ตัวแทน UTF8, เป็น UTF16 หรืออาจเป็น UTF32 หรือ UCS16 สำหรับ codepoint ขนาด 2 ไบต์ทั้งสามอาจเหมือนกันทั้งหมด
— Baxissimo

1

การค้นหาตัวละครที่ไม่ใช่ ASCII ทั้งหมดจะทำให้เกิดความรู้สึกว่าเป็นหนึ่งเดียวที่กำลังมองหาสตริง Unicode หรือตั้งใจที่จะดึงตัวละครที่พูดออกมาทีละตัว

สำหรับแบบเก่าให้ลองใช้วิธีใดวิธีหนึ่งต่อไปนี้ (ตัวแปรfileใช้สำหรับระบบอัตโนมัติ):

 file=file.txt ; LC_ALL=C grep -Piao '[\x80-\xFF\x20]{7,}' $file | iconv -f $(uchardet $file) -t utf-8

 file=file.txt ; pcregrep -iao '[\x80-\xFF\x20]{7,}' $file | iconv -f $(uchardet $file) -t utf-8

 file=file.txt ; pcregrep -iao '[^\x00-\x19\x21-\x7F]{7,}' $file | iconv -f $(uchardet $file) -t utf-8

วานิลลา grep ทำงานไม่ถูกต้องหากไม่มี LC_ALL = C ดังที่ระบุไว้ในคำตอบก่อนหน้า

ช่วง ASCII คือx00-x7Fช่องว่างx20เนื่องจากสตริงมีช่องว่างช่วงลบจะไม่แสดง

ช่วงที่ไม่ใช่ ASCII คือx80-xFFเนื่องจากสตริงมีช่องว่างช่วงบวกจะเพิ่มเข้าไป

คาดว่าสตริงจะมีอย่างน้อย 7 ตัวอักษรติดต่อกันภายในช่วง {7,}.

สำหรับเอาต์พุตที่อ่านได้โดยเชลล์ส่งuchardet $fileคืนการเดาการเข้ารหัสไฟล์ที่ส่งผ่านไปยัง iconv สำหรับการแก้ไขอัตโนมัติ


สิ่งนี้มีประโยชน์มากเนื่องจากมีการกล่าวถึงuchardetคำสั่ง ขอขอบคุณที่หัวขึ้น!
— bballdave025
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.