พิมพ์ส่วนเฉพาะในผลลัพธ์


11

ให้เราสมมติว่ามีคำสั่งเช่น:

cat /boot/config-3.19.0-32-generic | grep CONFIG_ARCH_DEFCONFIG

ผลลัพธ์เป็นเช่นนี้:

CONFIG_ARCH_DEFCONFIG="arch/x86/configs/x86_64_defconfig"

ตอนนี้คำถามของฉันคือ: มีคำสั่งใดบ้างที่จะพิมพ์เฉพาะสิ่งที่อยู่ภายในเครื่องหมายจุลภาคคว่ำคือ" "?

คุณช่วยอธิบายหน่อยได้ไหม? ขอขอบคุณ! ล่วงหน้า.


5
โปรดทราบว่าการใช้catในไปป์มักเป็นการสิ้นเปลืองทรัพยากร (AKA UUOC ) เกือบทุกครั้ง grepสามารถอ่านอินพุตจากไฟล์ได้แล้ว (เช่นgrep CONFIG_ARCH_DEFCONFIG /boot/config-3.19.0-32-genericทำสิ่งเดียวกัน แต่ 1. สั้นกว่า 2. เข้าใจง่ายกว่า 3. ไม่แยกเชลล์เพิ่มเติมและกระบวนการเพิ่มเติม) ใน 99% ของกรณีใช้ cat ที่จุดเริ่มต้นของไปป์โดยไม่ต้องต่อหลายไฟล์มันเป็นอันตราย :)
kos

@kos - Thanx! ไม่ทราบว่าเป็นเพราะฉันเพิ่งเริ่มใช้ลินุกซ์ จะเก็บไว้ในใจ
Raphael

Np! ฉันจะแสดงความคิดเห็นของฉันด้านบนสำหรับคนอื่นสะดุดคำถาม
kos

เริ่มต้นcatแม้ว่าจะไม่มีประโยชน์ในกรณีนี้จะทำให้การแก้ไขคำสั่งทั้งหมดในอนาคตง่ายขึ้นในกรณีที่คุณต้องการเปลี่ยน / เพิ่ม / ลบบางสิ่งบางอย่างในภายหลังอาจจะเป็นtrหรือcutฯลฯ ไม่จำเป็นต้องค้นหาและย้ายชื่อไฟล์ ตรวจสอบให้แน่ใจว่าคำสั่งอื่นรองรับ, ค้นหาตำแหน่งที่จะใส่ ฯลฯ และสำหรับไฟล์ทดสอบขนาดเล็กนั้นจะเพิ่ม 0.002 เท่านั้น (ฉันอาจใช้เวลามากกว่านี้ในการพิมพ์มากกว่าที่ฉันจะประหยัดได้ตลอดชีวิตในการหลีกเลี่ยงฟุ่มเฟือยcat)
Xen2050

1
@ Xen2050 ทำไมความcatช่วยเหลือที่นี่ คุณสามารถทำได้grep foo file | trหรือเพียงได้อย่างง่ายดายเช่น... | cut เพียงแค่เพิ่มพิเศษห้าตัวอักษร, ท่อพิเศษและมีสายเรียกโปรแกรมพิเศษและไม่ได้อะไรง่าย cat file | tr | grep ...cat
terdon

คำตอบ:


15

ใช่คุณสามารถทำได้ คำสั่งของคุณจะเป็น:

cat /boot/config-3.19.0-32-generic | grep CONFIG_ARCH_DEFCONFIG | awk -F'"' '{print $2}'

ซึ่งจะกลับมาเท่านั้น:

arch/x86/configs/x86_64_defconfig

awkคำสั่งใช้คั่นฟิลด์ด้วยคำสั่งและการตั้งค่าให้ใช้ราคาสองครั้งคุณพิมพ์ไว้ในที่มีราคาเดียวทั่วมันเหมือน-F -F'"'จากนั้นให้'{print $2}'บอก awk เพื่อพิมพ์ชุดที่สองหลังจากตัวคั่นฟิลด์

หวังว่านี่จะช่วยได้!


14
@Terrance ในกรณีนี้นี่คือการใช้งานไร้ประโยชน์และcat grepคุณสามารถใช้ทดแทนcatและ เป็นส่วนหนึ่งกับgrep awk -F'"' '/CONFIG_ARCH_DEFCONFIG/{print $2}' /boot/config-3.19.0-32-genericประปาน้อยลงปล่อยให้ AWK ทำงานทุกอย่างซึ่งเป็นมากกว่าที่ทำได้
Sergiy Kolodyazhnyy

เห็นด้วยกับ @Serg
Tung Tran

@Serg ไม่มีปัญหา ฉันเข้าใจสิ่งที่คุณพูด ฉันแค่เพิ่มไปยังคำสั่งเดิมของเขาโดยการเพิ่มawkคำสั่ง =)
Terrance

11

คุณสามารถทำได้ด้วยgrepคำสั่งเดียว:

grep -Po '^CONFIG_ARCH_DEFCONFIG="\K[^"]*' /boot/config-3.19.0-32-generic

หรือ (อีกต่อไปอีกเล็กน้อยและ convulted มากขึ้น):

grep -Po '^CONFIG_ARCH_DEFCONFIG="\K.*?(?=")' /boot/config-3.19.0-32-generic
  • -P: บอกgrepให้ตีความรูปแบบเป็น PCRE (Perl Compatible Normal Expression);
  • -o: บอกgrepให้พิมพ์เฉพาะการแข่งขัน;
  • ^CONFIG_ARCH_DEFCONFIG=": จับคู่CONFIG_ARCH_DEFCONFIG="สตริงที่จุดเริ่มต้นของบรรทัด;
  • \K: ทิ้งสตริงย่อยที่ตรงกันก่อนหน้า;

# 1:

  • [^"]*: ตรงกับจำนวนอักขระใด ๆ ที่ไม่ใช่"(อย่างตะกละตะกลาม)

# 2:

  • .*?: ตรงกับจำนวนอักขระใด ๆ (ขี้เกียจ);
  • (?="): lookahead (การยืนยันแบบ zero-lenght ไม่ตรงกับอักขระใด ๆ ); "การแข่งขันถ้าตัวอักษรต่อไปนี้คือ
% grep -Po '^CONFIG_ARCH_DEFCONFIG="\K[^"]*' /boot/config-4.2.0-16-generic
arch/x86/configs/x86_64_defconfig
% grep -Po '^CONFIG_ARCH_DEFCONFIG="\K.*?(?=")' /boot/config-4.2.0-16-generic
arch/x86/configs/x86_64_defconfig

ฉันรักการเรียนรู้มากกว่าหนึ่งวิธีเพื่อให้ได้ผลลัพธ์เดียวกัน คำตอบที่ดี! =)
Terrance

10

มีหลายวิธีในการดูแลแมวตัวนี้นี่คือsedวิธี:

sed -nr 's/^CONFIG_ARCH_DEFCONFIG="([^"]+)"$/\1/p' /boot/config-3.19.0-32-generic

ที่นี่เราจับคู่บรรทัดและจับภาพส่วนที่ต้องการเช่นส่วนที่อยู่ในเครื่องหมายคำพูดคู่ ( ([^"]+)) จากนั้นแทนที่ทั้งบรรทัดด้วยกลุ่มที่จับ ( \1) เท่านั้น

ตัวอย่าง:

% sed -nr 's/^CONFIG_ARCH_DEFCONFIG="([^"]+)"$/\1/p' /boot/config-3.13.0-32-generic
arch/x86/configs/x86_64_defconfig

10

อะไรไม่perl?

grep CONFIG_ARCH_DEFCONFIG /boot/config-3.19.0-32-generic | 
    perl -pe 's/.*?"([^"]*).*/$1/'

perlจะ-print -eทุกบรรทัดหลังจากการใช้สคริปต์ที่กำหนดโดย s/foo/bar/จะแทนด้วยfoo barรูปแบบในวงเล็บคือ "ถูกจับ" และสามารถเรียกได้ว่า$1, $2... $Nซึ่ง$1เป็นรูปแบบที่ 1 ที่ถูกจับ$2ที่สอง ฯลฯ นิพจน์ปกติจะมองหาทุกอย่างจนกระทั่งเครื่องหมายแรก ( .*?") จากนั้นจับ 0 หรือมากกว่า"อักขระที่ไม่ใช่( [^"]*) แล้วทุกอย่างอื่น สิ่งทั้งหมดจะถูกแทนที่ด้วยรูปแบบการจับ

นอกจากนี้คุณยังสามารถปล่อยรูปแบบการจับคู่ไว้ที่perl:

perl -ne 's/.*CONFIG_ARCH_DEFCONFIG="([^"]*).*/$1/ && print' /boot/config-3.19.0-32-generic

2
ฉันรู้ว่าคุณจะเข้าร่วมในบางจุด: P +1
heemayl

ฉันจะสร้างรหัสไพ ธ อน
Avinash Raj

with open('/boot/config-3.19.0-32-generic') as f: for line in f: if line.startswith('CONFIG_ARCH_DEFCONFIG'): print line.split('"')[1]
Avinash Raj

@AvinashRaj สิ่งที่ดีโปรดโพสต์นี้โปรด? ฉันโพสต์หนึ่งด้วย regex เช่นกัน
Sergiy Kolodyazhnyy

8

นี่คือการรวมกันของgrepและcutที่ทำงานเดียวกัน

$ grep "CONFIG_ARCH_DEFCONFIG" /boot/config-3.19.0-32-generic | cut -d"\"" -f2                                                
arch/x86/configs/x86_64_defconfig

คำอธิบาย:

  • grep "CONFIG_ARCH_DEFCONFIG" /boot/config-3.19.0-32-genericเป็นส่วนหนึ่งที่พบว่าเส้นในไวยากรณ์ grep grep [OPTIONS] PATTERN [FILE...]มาตรฐาน: เอาท์พุทจะผ่านท่อไปยังขั้นตอนต่อไป
  • cut -d"\"" -f2. ส่วนนี้ใช้ข้อความตัดเพื่อตัดส่วนครอบตัดคั่นด้วยตัวคั่นเฉพาะ (ซึ่งระบุด้วย-dแฟล็ก) เราต้องหลบหนีอัญประกาศคู่ด้วยแบ็กสแลชเพื่อให้เชลล์อนุญาตให้รับอัญประกาศคู่เป็นหนึ่งในตัวเลือกไปยังcutคำสั่งแทนที่จะป้อนไปยังเชลล์เอง ตอนนี้cutจะรักษาเอาท์พุทจากgrepเป็นแยกออกจากกัน"และแยกออกเป็นสามคอลัมน์CONFIG_ARCH_DEFCONFIG, arch/x86/configs/x86_64_defconfigและพื้นที่ว่างเปล่า บรรทัดที่เราต้องการคือคอลัมน์ที่สองนั่นหมายความว่าเราต้องใช้การ-f2ตั้งค่าสถานะ

3

เนื่องจากฉันกำลังเรียนรู้pythonที่นี่เป็นรุ่นที่ใช้ตรงนั้น

#!/usr/bin/env python
import re

reg = re.compile('CONFIG_ARCH_DEFCONFIG')

with open("/boot/config-3.19.0-32-generic") as file :
   for line in file:
       if reg.match(line):
           print line.split('"')[1]

วิ่งตัวอย่าง:

DIR:/TECH-BOOKS
skolodya@ubuntu:$ ./extractString.py                                           
arch/x86/configs/x86_64_defconfig

DIR:/TECH-BOOKS
skolodya@ubuntu:$ cat ./extractString.py                                       
#!/usr/bin/env python
import re

reg = re.compile('CONFIG_ARCH_DEFCONFIG')

with open("/boot/config-3.19.0-32-generic") as file :
   for line in file:
       if reg.match(line):
           print line.split('"')[1]

การเยื้องเป็นสิ่งที่สำคัญมากในงูหลาม .. 7
Avinash Raj

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