grep a tab ใน UNIX


417

ฉันจะgrepแท็บ (\ t) ในไฟล์บนแพลตฟอร์ม Unix ได้อย่างไร


53
เพียงแค่ใช้grep "<Ctrl+V><TAB>"มันทำงาน: (ถ้าเป็นครั้งแรกประเภทgrep "แล้วกด Ctrl + V คีย์คำสั่งผสมแล้วกดปุ่ม TAB แล้วพิมพ์"และกด Enter, Voila!)
โกง

16
ctrl + v เป็นไอเดียที่ไม่ดีจริงๆ! ... ใช่มันอาจทำงานได้จากคำสั่งคอนโซล แต่อาจไม่สามารถพิมพ์ได้ใน SCRIPT (คุณอยู่ในความเมตตาของบรรณาธิการเช่นฉันใช้ mcedit และ ctrl + v ไม่ทำงานที่นั่น)
THESorcerer

ที่เกี่ยวข้อง แต่ไม่ซ้ำกัน: ค้นหาแท็บโดยไม่มี -P โดยใช้ 'grep'
Peter Mortensen

ดูเพิ่มเติม: askubuntu.com/questions/53071/... (เชื่อมโยงด้านล่างเช่นกัน)
Shiri

คำตอบ:


374

หากใช้ GNU grep คุณสามารถใช้ regexp แบบ Perl ได้:

grep -P '\t' *

ดูเหมือนจะไม่ทำงานกับรูปแบบของฉัน ความพยายามในการใช้ไวยากรณ์นั้นไม่พิมพ์อะไรเลย (ตัวแปร Mac OS X แตกต่างกันหรือไม่)
futureelite 7

2
@futureelite: จากเอกสารของ Apple ( developer.apple.com/Mac/library/documentation/Darwin/Reference/… ) โปรแกรม grep Mac OS X ควรสนับสนุนตัวเลือก -P ลองสร้างคำถามใหม่ที่ superuser.com
ผ่อนคลาย

3
ดีมากสำหรับ GNU UNIX แต่ POSIX Solaris, AIX และ HP-UX เป็นอย่างไร พวกนั้นไม่รู้อะไรเลยเกี่ยวกับ-Pทางเลือก
rook

21
@rook GNU ไม่ใช่ UNIX
Lily Chung

5
ใน Mac OSX คุณสามารถกำหนดรูปแบบโดยใช้ -e
Faisal Feroz

314

เคล็ดลับคือการใช้เครื่องหมาย $ ก่อนราคาเดียว นอกจากนี้ยังใช้งานได้กับเครื่องมือตัดและอื่น ๆ

grep $'\t' sample.txt

7
เคล็ดลับช่วยชีวิตช่วยชีวิต! มันทำงานได้zshดีเท่าที่ฉันจะบอกได้ คุณสามารถแสดงความคิดเห็นเกี่ยวกับความหมายของ$สัญลักษณ์นั้นได้อย่างไร
Romain

2
ไม่ทำงานหากสตริงมีสิ่งอื่นนอกเหนือจาก '\ t' คุณจะค้นหาตัวอย่างเช่น "\ t" (แท็บ + ช่องว่าง) ได้อย่างไร
Raman

6
รามัน: $'\t'' 'คุณสามารถใช้ ตัวอย่างจริงที่แสดงให้เห็นว่าการทำงานยังมีการดวลจุดโทษ (ทุบตีไม่เพียง แต่ที่ไม่ได้โดยเริ่มต้นที่ติดตั้งบน Android) busybox grep -oE '^nodev'$'\t''fuse$' /proc/filesystemsเป็น
v6ak

5
ฉันคิดว่า $ '... ' เป็นสำนวนที่ทุบตี อาจไม่ทำงานในดวลจุดโทษ Dunno เกี่ยวกับ csh หรือ tcsh
Edward Falk

5
จาก 'man bash': คำของฟอร์ม $ 'string' ได้รับการปฏิบัติเป็นพิเศษ คำนี้ขยายออกเป็นสตริงด้วยอักขระเครื่องหมายทับขวาทับกลับแทนที่ตามที่ระบุโดยมาตรฐาน ANSI C ลำดับหนีทับขวาถ้าปัจจุบันจะถูกถอดรหัส ...
broeni

84

ฉันไม่เคยจัดการให้ metacharacter '\ t' ทำงานร่วมกับ grep ได้ อย่างไรก็ตามฉันพบวิธีแก้ไขปัญหาสองวิธี:

  1. ใช้<Ctrl-V> <TAB>(กดปุ่ม Ctrl-V แล้วพิมพ์แท็บ)
  2. ใช้ awk: foo | awk '/\t/'

4
| awk '/\t/'ทางออกที่จะทำงานให้เปลือกหอยทุกแพลตฟอร์มและระบบ
Samveen

6
+1 สำหรับโซลูชัน POSIX แบบพกพาและไม่ใช้ bashisms, zshism, GNUism และ linuxisms
Jens

1
ctrl-V ไม่มีประโยชน์หากคุณต้องการคัดลอก (จากบันทึกย่อหรือสคริปต์) ควรใช้โซลูชันที่ชัดเจนซึ่งมีแท็บ '\ t' ตามตัวอักษร (เช่นตัวที่ดูเหมือน whitespace) ที่มองเห็นได้บ่อยครั้งจะถูกแปลงเป็น SPC เมื่อ
คัดลอก

awkทำงานได้ดีที่นี่ แต่ในการทดสอบบางอย่างในเครื่องของฉันกับไฟล์ขนาดใหญ่มากมันเป็นประมาณ 30% grep -Pช้ากว่าการใช้ นี่อาจเป็นเรื่องเล็กน้อยและไม่เกี่ยวข้องตามกรณีการใช้งานและawkอาจดีกว่าสำหรับการอ่านและการพกพา
theferrit32

43

จากคำตอบนี้ใน Ask Ubuntu:

บอก grep ให้ใช้นิพจน์ทั่วไปตามที่กำหนดโดย Perl (Perl มี \tตามแท็บ):

grep -P "\t" <file name>

ใช้อักขระแท็บตัวอักษร:

grep "^V<tab>" <filename>

ใช้printfเพื่อพิมพ์อักขระแท็บสำหรับคุณ:

grep "$(printf '\t')" <filename>

1
คำต่อคำจากhttp://askubuntu.com/a/53096/453741
villapx

ctrl-V ไม่มีประโยชน์หากคุณต้องการคัดลอก (จากบันทึกย่อหรือสคริปต์) ควรใช้โซลูชันที่ชัดเจนซึ่งมีแท็บ '\ t' ตามตัวอักษร (เช่นตัวที่ดูเหมือน whitespace) ที่มองเห็นได้บ่อยครั้งจะถูกแปลงเป็น SPC เมื่อ
คัดลอก

31

วิธีหนึ่งคือ (นี่คือกับ Bash)

grep -P '\t'

-P เปิดใช้การแสดงผลปกติของ Perl ดังนั้น \ t จะทำงาน

ตามที่ผู้ใช้กล่าวว่าผ่อนคลายอาจเป็นข้อมูลเฉพาะของ GNU grep ทางเลือกคือแทรกแท็บอย่างแท้จริงหากเชลล์ตัวแก้ไขหรือเทอร์มินัลอนุญาต


ตัวเลือก P ที่ไม่รู้จักในเปลือก ksh
ชิน Chourasiya

อย่างที่บอกว่าผ่อนคลายอาจจะเฉพาะกับ GNU grep เพียงแค่ชี้แจง
tjmoore

คุณจะเพิ่มแท็บได้อย่างไร มันไม่เริ่มต้นกระบวนการทำให้สมบูรณ์โดยอัตโนมัติเมื่อคุณกดปุ่มแท็บหรือไม่ (ที่อาจทำงานในสคริปต์ทุบตี แต่ไม่ได้อยู่ในบรรทัดคำสั่ง)
AntonioCS

1
@AntonioCS ตามที่ระบุไว้ข้างต้นโดย SamKrieg เพื่อให้เชลล์อนุญาตให้คุณพิมพ์อักขระใด ๆ ให้พิมพ์ CTRL-v ก่อน ดูเพิ่มเติมaskubuntu.com/questions/53071/…
เดนิสอาร์นาด์

2
-P ใช้เฉพาะ grep ไม่ใช่เชลล์ใด ๆ -P ควรทำงานในเชลล์ใด ๆ หากมีการติดตั้ง grep GNU
plijnzaad

13

อีกวิธีในการแทรกแท็บอย่างแท้จริงภายในนิพจน์คือการใช้$'\t'คำพูดที่ไม่ค่อยมีคนรู้จักใน Bash:

grep $'foo\tbar'        # matches eg. 'foo<tab>bar'

(โปรดทราบว่าหากคุณกำลังจับคู่สำหรับสตริงคงที่คุณสามารถใช้สิ่งนี้กับโหมด '-F')

บางครั้งการใช้ตัวแปรสามารถทำให้สัญกรณ์อ่านง่ายขึ้นและสามารถจัดการได้มากขึ้น:

tab=$'\t'               # `tab=$(printf '\t')` in POSIX
id='[[:digit:]]\+'
name='[[:alpha:]_][[:alnum:]_-]*'
grep "$name$tab$id"     # matches eg. `bob2<tab>323`

10

นี่ไม่ใช่สิ่งที่คุณกำลังมองหา แต่อาจใช้ได้ในกรณีของคุณ

grep '[[:blank:]]'

เทียบเท่ากับ

grep -P '[ \t]'

ดังนั้นมันจะค้นหา Space และ Tab

classes คลาสของตัวละคร

หมายเหตุมันไม่ได้โฆษณาในของฉันman grepแต่ยังใช้งานได้

$ man grep | grep blank | ห้องน้ำ
      0 0 0

@ A-letubby ตอนนี้ใช้ได้กับการแก้ไขแล้ว - -Pเพิ่มอาร์กิวเมนต์แล้ว
villapx


6

โดยทั่วไปมีสองวิธีในการแก้ไข:

  1. ( แนะนำ ) ใช้ไวยากรณ์นิพจน์ปกติที่สนับสนุนโดย grep (1) Modern grep (1) รองรับสองรูปแบบของ POSIX 1003.2 ไวยากรณ์ regex: REs พื้นฐาน (ล้าสมัย) และREs สมัยใหม่ ไวยากรณ์ถูกอธิบายในรายละเอียดเกี่ยวกับ re_format (7) และ regex (7) man pages ซึ่งเป็นส่วนหนึ่งของระบบ BSD และ Linux ตามลำดับ grep GNU (1) ยังรองรับ REs ที่เข้ากันได้กับ Perl ซึ่งจัดทำโดยไลบรารี pcre (3)

    ในภาษา regex สัญลักษณ์แท็บมักจะถูกเข้ารหัสโดย\tอะตอม อะตอมได้รับการสนับสนุนโดย BSD ที่ขยายการแสดงออกปกติ ( egrep, grep -Eบนระบบที่เข้ากันได้กับ BSD), เช่นเดียวกับ REs ที่เข้ากันได้กับ Perl ( pcregrep, GNU grep -P)

    ทั้งการแสดงออกปกติขั้นพื้นฐานและ REs \tลินุกซ์ขยายเห็นได้ชัดว่ามีการสนับสนุนไม่มี โปรดศึกษาหน้ายูทิลิตี UNIX เพื่อทราบว่าภาษา regex รองรับ (ดังนั้นความแตกต่างระหว่าง sed (1), awk (1) และ pcregrep (1) นิพจน์ทั่วไป)

    ดังนั้นบน Linux:

    $ grep -P '\t' FILE ...
    

    บนระบบ BSD เหมือนกัน:

    $ egrep '\t' FILE ...
    $ grep -E '\t' FILE ...
    
  2. ส่งอักขระแท็บเป็นรูปแบบ สิ่งนี้ตรงไปตรงมาเมื่อคุณแก้ไขไฟล์สคริปต์:

    # no tabs for Python please!
    grep -q '   ' *.py && exit 1
    

    อย่างไรก็ตามเมื่อทำงานในเชลล์แบบโต้ตอบคุณอาจต้องพึ่งพาความสามารถของเชลล์และเทอร์มินัลเพื่อพิมพ์สัญลักษณ์ที่เหมาะสมลงในบรรทัด ในเทอร์มินัลส่วนใหญ่สิ่งนี้สามารถทำได้ผ่านการรวมแป้นCtrl+ Vซึ่งสั่งให้เทอร์มินัลรักษาอักขระอินพุตถัดไปตามตัวอักษรอย่างแท้จริง ( Vสำหรับ "คำต่อคำ"):

    $ grep '<Ctrl>+<V><TAB>' FILE ...
    

    เชลล์บางตัวอาจให้การสนับสนุนขั้นสูงสำหรับการเรียงพิมพ์คำสั่ง เช่นในคำทุบตี (1) ของรูปแบบ$'string'ได้รับการปฏิบัติเป็นพิเศษ:

    bash$ grep $'\t' FILE ...
    

    โปรดทราบว่าแม้ว่าจะดีในบรรทัดคำสั่งสิ่งนี้อาจสร้างปัญหาความเข้ากันได้เมื่อสคริปต์จะถูกย้ายไปยังแพลตฟอร์มอื่น นอกจากนี้ควรระวังด้วยคำพูดเมื่อใช้พิเศษโปรดปรึกษาทุบตี (1) สำหรับรายละเอียด

    สำหรับเชลล์เป้าหมาย (และไม่เพียง แต่) ลักษณะการทำงานเดียวกันอาจเลียนแบบโดยใช้การทดแทนคำสั่งเพิ่มเติมโดย printf (1) เพื่อสร้าง regex ที่เหมาะสม:

    $ grep "`printf '\t'`" FILE ...
    


2

ใช้ gawk ตั้งค่าตัวคั่นฟิลด์เป็นแท็บ (\ t) และตรวจสอบจำนวนฟิลด์ หากมากกว่า 1 แสดงว่ามี / มีแท็บอยู่

awk -F"\t" 'NF>1' file

2
นี่เป็นเรื่องที่เกินความจริงเล็กน้อยและคิดถึงคำถามนี้ awk /\t/เพียงพอสำหรับคำถามของ op
การชดเชย จำกัด

2

ทางเลือกที่ดีคือใช้ 'sed as grep' (ตามที่อธิบายไว้ในบทช่วยสอนแบบคลาสสิคนี้)

sed -n 's/pattern/&/p' file

ตัวอย่าง (ทำงานใน bash, sh, ksh, csh, .. ):

[~]$ cat testfile
12 3
1 4 abc
xa      c
        a       c\2
1 23

[~]$ sed -n 's/\t/&/p' testfile 
xa      c
        a       c\2

[~]$ sed -n 's/\ta\t/&/p' testfile
        a       c\2

1

วิธี +1 ที่ทำงานใน ksh, dash ฯลฯ : ใช้ printf เพื่อแทรก TAB:

grep "$(printf 'BEGIN\tEND')" testfile.txt

สิ่งนี้ไม่ได้ผลสำหรับฉันใน Ubuntu Trusty (Bash 4.3.11) สิ่งต่อไปนี้ใช้งานได้แม้ว่า:grep "$(printf '\t')" testfile.txt
Josh Rumbut

0

คำตอบนั้นง่ายกว่า เขียน grep ของคุณและในเครื่องหมายคำพูดพิมพ์แท็บมันทำงานได้ดีอย่างน้อยใน ksh

grep "  " *

3
แรกที่คุณต้องจัดการเพื่อป้อนตัวอักษร TAB ในเปลือกของคุณ - หอยส่วนใหญ่ตีความคีย์นี้เป็นคำสั่ง (เสร็จสิ้น)
Kaii


0

การใช้วิธีการ 'sed-as-grep' แต่การแทนที่แท็บด้วยตัวอักษรที่มองเห็นได้ของการตั้งค่าส่วนตัวเป็นวิธีที่ฉันชอบเพราะมันแสดงให้เห็นอย่างชัดเจนว่าไฟล์ใดที่มีข้อมูลที่ร้องขอและวางไว้ในบรรทัด:

sed -n 's/\t/\*\*\*\*/g' file_name

หากคุณต้องการใช้ข้อมูลบรรทัด / ไฟล์หรือตัวเลือก grep อื่น ๆ แต่ยังต้องการเห็นการแทนที่อักขระแท็บที่มองเห็นได้คุณสามารถทำได้โดย

grep -[options] -P '\t' file_name | sed 's/\t/\*\*\*\*/g'

ตัวอย่างเช่น:

$ echo "A\tB\nfoo\tbar" > test
$ grep -inH -P '\t' test | sed 's/\t/\*\*\*\*/g'
test:1:A****B
test:2:foo****bar

แก้ไข: เห็นได้ชัดว่าข้างต้นจะเป็นประโยชน์สำหรับการดูเนื้อหาไฟล์เพื่อค้นหาแท็บ - หากวัตถุประสงค์คือการจัดการแท็บเป็นส่วนหนึ่งของเซสชั่นการเขียนสคริปต์ที่ใหญ่กว่านี้ไม่ได้มีวัตถุประสงค์ที่เป็นประโยชน์ใด ๆ


0

สิ่งนี้ทำงานได้ดีสำหรับ AIX ฉันกำลังค้นหาบรรทัดที่มีJOINED<\t>ACTIVE

voradmin cluster status | grep  JOINED$'\t'ACTIVE

 vorudb201   1       MEMBER(g) JOINED        ACTIVE
*vorucaf01   2       SECONDARY JOINED        ACTIVE

0

คุณอาจต้องการใช้ grep "$(echo -e '\t')"

ข้อกำหนดเพียงอย่างเดียวคือechoสามารถตีความเครื่องหมายแบคสแลชได้


0

วิธีการจำแนกเลขฐานสองทางเลือกเหล่านี้ทำงานได้อย่างสมบูรณ์ และฉันชอบของที่ใช้ awk มากเพราะฉันจำการใช้ไวยากรณ์ด้วยตัวอักษรไบนารีไม่ได้เลย อย่างไรก็ตามมันควรจะเป็นไปได้ที่จะกำหนดค่าตัวแปรเชลล์ในแบบพกพา POSIX (เช่น TAB = echo "@" | tr "\100" "\011") แล้วใช้จากที่นั่นทุกที่ในแบบพกพา POSIX; เช่นกัน (เช่นชื่อไฟล์ grep "$ TAB") ในขณะที่โซลูชันนี้ทำงานได้ดีกับ TAB มันจะทำงานได้ดีกว่าตัวอักษรไบนารีอื่น ๆ เมื่อใช้ค่าไบนารีอื่นที่ต้องการในการกำหนด (แทนค่าสำหรับอักขระ TAB เป็น 'tr')


0

เครื่องหมาย $ '\ t' ที่ระบุในคำตอบอื่น ๆ เป็นแบบเฉพาะเชลล์ - ดูเหมือนว่าจะใช้งานได้กับ bash และ zsh แต่ไม่ใช่แบบทั่วไป

หมายเหตุ: ข้อมูลต่อไปนี้ใช้สำหรับfishเชลล์และไม่ทำงานในการทุบตี :

ในfishเชลล์หนึ่งสามารถใช้ unquote \tตัวอย่างเช่น:

grep \t foo.txt

หรือสามารถใช้สัญลักษณ์ hex หรือ unicode เช่น:

grep \X09 foo.txt
grep \U0009 foo.txt

(สัญลักษณ์เหล่านี้มีประโยชน์สำหรับตัวละครลึกลับเพิ่มเติม)

เนื่องจากค่าเหล่านี้ต้องไม่ถูกอ้างอิงจึงสามารถรวมค่าที่ยกมาและไม่ได้อ้างอิงโดยการต่อข้อมูล

grep "foo"\t"bar"

-4

คุณสามารถพิมพ์

grep \ t foo

หรือ

grep '\ t' foo

เพื่อค้นหาอักขระแท็บในไฟล์ foo คุณอาจทำรหัสหลบหนีอื่น ๆ ได้เช่นกัน แต่ฉันเพิ่งทดสอบ \ n แม้ว่าจะค่อนข้างใช้เวลานานและไม่ชัดเจนว่าทำไมคุณต้องการใน zsh คุณยังสามารถพิมพ์อักขระแท็บกลับไปที่จุดเริ่มต้น grep และล้อมรอบแท็บด้วยเครื่องหมายคำพูด


-6

มองหาช่องว่างหลาย ๆ ครั้ง[[: space:]] *

grep [[: space:]] * '.' '.'

จะพบสิ่งนี้:

'แท็บ' ..

นี่คือใบเสนอราคาเดียว (') และไม่ใช่สองเท่า (")
นี่คือวิธีที่คุณทำการต่อข้อมูลแบบ grep = -)

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