บรรทัดคำสั่ง: แยกสตริงย่อยออกจากเอาต์พุต


25

สมมติว่าฉันรันคำสั่ง SayStuff

$ SayStuff

และผลลัพธ์คือ

Watermelons and cucumbers

ตอนนี้ สมมติว่าฉันต้องการแยกสตริงย่อยcucumbersจากเอาต์พุตและไพพ์ลงในบางสิ่ง
วิธีที่ฉันจะไปเกี่ยวกับเรื่องนี้ทางโปรแกรมจะแบ่งการส่งออกเป็นอาร์เรย์โดยคั่นอวกาศArrayName[2]และการอ้างอิงได้โดย ฉันค่อนข้างใหม่กับเชลล์สคริปท์และประสบความสำเร็จในการขุดcutตัวอย่างแบบกึ่งความลับเท่านั้นซึ่งไม่มีเหตุผล

ความคิดใด ๆ

คำตอบ:


30
$ echo "Watermelons and cucumbers" | cut -d ' ' -f 3
cucumbers

การ-d ' 'บอกcutให้แบ่งช่องว่าง -f 3เลือกคอลัมน์ที่สาม

นอกจากนี้คุณยังสามารถใช้awkซึ่งจะแยกตามพื้นที่แล้วและทำให้คอลัมน์ใช้ได้เป็น$1, $2...

$ echo "Watermelons and cucumbers" | awk '{ print $3 }'
cucumbers

โปรดทราบว่าcutจะไม่จัดการกับช่องว่างจำนวนตัวแปรในขณะที่awkทำ
Zitrax

13

ฉันอาจจะใช้หนึ่งในตัวเลือกที่ได้รับจาก @slhck แล้ว แต่นี่เป็นวิธีการอีกสองสามวิธี:

  1. ใช้อาร์เรย์เหมือนที่คุณใช้ในภาษาอื่น:

    $ foo=( $(SayStuff) ) 
    $ echo ${foo[2]}
    cucumbers

    var=()ประกาศอาร์เรย์$(command)บันทึกผลลัพธ์ของคำสั่งที่ ดังนั้นfoo=( $(SayStuff) )ร้านค้าการส่งออกของSayStuffลงในอาร์เรย์fooและ yuou แล้วมันเป็นองค์ประกอบที่สามด้วยecho${foo[2]}

  2. sed

    $ SayStuff | sed 's/.* \(.*\)/\1/'
    cucumbers

    sedคำสั่งจะแทน ( s///) ทุกอย่างด้วยคำพูดสุดท้าย regex ตรงกับอะไรถึงพื้นที่ ( .*) (\(.*\)ซึ่งจะตรงกับทุกอย่างขึ้นอยู่กับพื้นที่ที่ผ่านมาและจากนั้นก็จับคำพูดสุดท้าย \1ตั้งแต่คำที่ได้รับการจับเราสามารถเรียกมันว่า

    รุ่นที่ง่ายกว่า:

    $ SayStuff | sed 's/.* //'
    cucumbers
  3. ทุบตี

    $ foo=$(SayStuff); echo ${foo##* } 
    cucumbers

    สิ่งนี้ใช้ความสามารถในการจัดการสตริงของ bash ดูที่นี่สำหรับรายละเอียดเพิ่มเติม

  4. ทุบตีมากขึ้น

    $ SayStuff | while read a b c; do echo $c; done
    cucumbers
  5. Perl ซึ่งแน่นอนว่ามีหลายวิธีในการทำเช่นนี้:

    $ SayStuff | perl -lane 'print $F[$#F]'
    cucumber

    -aทำให้perlทำตัวเหมือนเส้นแยกที่ช่องว่างและบันทึกลงในอาร์เรย์awk @Fจากนั้นเราจะพิมพ์องค์ประกอบสุดท้ายของ@F( $#Fคือจำนวนองค์ประกอบใน@F) -lบอก Perl จะเพิ่มขึ้นบรรทัดใหม่ให้กับแต่ละprintคำสั่งที่-nว่ามันควรจะดำเนินการสาย STDIN โดยสายและ-eว่ามันควรจะเรียกใช้สคริปต์ที่กำหนดในบรรทัดคำสั่ง

    $ SayStuff | perl -pe 's/.* //'
    cucumber

    ตัวเลือกถูกอธิบายไว้ด้านบนเราเพิ่งลบทุกอย่างจนถึงพื้นที่สุดท้ายและการพิมพ์ ( -p)

    $ perl -le 'print $ARGV[$#ARGV]' $(SayStuff)
    cucumbers

    ที่นี่เราจะผ่านไปWatermelons and cucumbersเป็นข้อโต้แย้งซึ่ง Perl จะบันทึกในอาร์เรย์และเพื่อให้เราพิมพ์องค์ประกอบสุดท้ายของ@ARG@ARG

  6. การใช้กลอุบาย อันนี้ใช้sedสำหรับแปลงช่องว่างเป็นบรรทัดใหม่แล้วtailพิมพ์เฉพาะบรรทัดสุดท้าย

    $ SayStuff | sed 's/ /\n/g' | tail -n 1
    cucumbers
  7. grep และนิพจน์ทั่วไปโดยใช้-oซึ่งจะพิมพ์เฉพาะสตริงที่ตรงกัน

    $ SayStuff | grep -Po '\w+$' 
    cucumbers
  8. การโกง

    $ SayStuff | grep -o cucumbers
    cucumbers

2

นี่คือคำอธิบายเพิ่มเติมบางส่วน:

Usage: cut OPTION... [FILE]...

Print selected parts of lines from each FILE to standard output.

   -d, --delimiter=DELIM
          use DELIM instead of TAB for field delimiter

   -f, --fields=LIST
          select only these fields;  also print any line that contains  no
          delimiter character, unless the -s option is specified

ดังนั้นถ้าคุณต้องการฟิลด์ที่ 3 และคั่นด้วยช่องว่าง '' ก็คือ

$ echo "Watermelons and cucumbers" | cut -d ' ' -f 3  
cucumbers

ถ้าคุณต้องการLASTฟิลด์คุณอาจจะใช้awk
ในกรณีนี้มันจะกลายเป็น:

$ echo "แตงโมและแตงกวา" | awk '{พิมพ์ $ NF}'
แตงกวา

ในawkNF คือจำนวนฟิลด์ในบรรทัดดังนั้น$NFหมายถึงฟิลด์สุดท้ายในบรรทัด


โดยทั่วไปคำถามเดียวกันอยู่ที่นี่ แต่โดยทั่วไปมากกว่า: stackoverflow.com/questions/3162385/ ...... ใช่คุณสามารถใช้วิธีอื่น ๆ แต่ awk นั้นสั้นที่สุด
zeridon
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.