ฉันจะ 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 LIVEE! あいうえお かが アイウエオ カガ   ซฌ आइ  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 LIVEE! あいうえお かが アイウエオ カガ   ซฌ आइ  YEOW, mix of japanese and chars from other
34 52 LIVEE! あいうえお かが アイウエオ カガ   ซฌ आइ  YEOW, mix of japanese and chars from other
73 LIVEE! あいうえお かが アイウエオ カガ   ซฌ आइ  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.