การแยกสตริงโดยการเกิดขึ้นครั้งแรกของตัวคั่น


54

ฉันมีสตริงในรูปแบบถัดไป

id;some text here with possible ; inside

และต้องการที่จะแยกมันถึง 2 ;สายโดยเกิดขึ้นครั้งแรกของ ดังนั้นควร: idและsome text here with possible ; inside

ฉันรู้วิธีแยกสตริง (ตัวอย่างเช่นด้วยcut -d ';' -f1) แต่มันจะแยกส่วนเพิ่มเติมเนื่องจากฉันมี;อยู่ในส่วนด้านซ้าย


หลังจากแยกสตริงแล้วคุณต้องการทำอะไรกับ "id" คุณต้องการกำหนดให้ตัวแปรพิมพ์ออกมาหรือไม่?
Daemon of Chaos

ฉันจะมี 2 ตัวแปร: idและstring
gakhov

คำตอบ:


65

cut ดูเหมือนเครื่องมือที่เหมาะสมสำหรับสิ่งนี้:

bash-4.2$ s='id;some text here with possible ; inside'

bash-4.2$ id="$( cut -d ';' -f 1 <<< "$s" )"; echo "$id"
id

bash-4.2$ string="$( cut -d ';' -f 2- <<< "$s" )"; echo "$string"
some text here with possible ; inside

แต่readเหมาะกว่า:

bash-4.2$ IFS=';' read -r id string <<< "$s"

bash-4.2$ echo "$id"
id

bash-4.2$ echo "$string"
some text here with possible ; inside

3
ที่ดี! มันใช้งานได้เหมือนมีเสน่ห์! ฉันจะเลือกตั้งแต่ฉันใช้read bashขอบคุณ @ manatwork!
gakhov

cutวิธีการจะทำงานเฉพาะเมื่อ "$ s" ไม่ได้มีตัวอักษรขึ้นบรรทัดใหม่ read อยู่ในเชลล์คล้ายบอร์นใด ๆ <<< อยู่ใน rc, zsh และ bash และ ksh93 รุ่นล่าสุดและเป็นอันที่ไม่ได้มาตรฐาน
Stéphane Chazelas

โอ๊ะคุณพูดถูกแล้ว @StephaneChazelas ใจของฉันเป็น-aด้วยเหตุผลบางอย่างเมื่อเอ่ยถึง'sbash read(เห็นได้ชัดว่าไม่มีประโยชน์ที่นี่)
จัดการ

ฉันลืมที่จะพูดถึงว่าวิธีการอ่านไม่ได้ผลถ้า $ s มีอักขระขึ้นบรรทัดใหม่ ฉันได้เพิ่มคำตอบของฉันเอง
Stéphane Chazelas

1
ฉันต้องการเน้นเส้นประต่อท้าย-f 2-ในstring="$( cut -d ';' -f 2- <<< "$s" )"; echo "$string"คำสั่ง นี่คือสิ่งที่ละเว้นส่วนที่เหลือของตัวคั่นในสตริงสำหรับงานพิมพ์ ไม่ชัดเจนเมื่อดูหน้าคนcut
Steen

17

ด้วย sh มาตรฐานใด ๆ (รวมถึง bash):

sep=';'
case $s in
  (*"$sep"*)
    before=${s%%"$sep"*}
    after=${s#*"$sep"}
    ;;
  (*)
    before=$s
    after=
    ;;
esac

readโซลูชันพื้นฐานจะทำงานกับอักขระเดี่ยว (และบางเชลล์, ไบต์เดียว) ค่า$sepอื่น ๆ นอกเหนือจากช่องว่าง, แท็บหรือขึ้นบรรทัดใหม่และเฉพาะในกรณีที่$sไม่มีอักขระขึ้นบรรทัดใหม่

cutโซลูชันพื้นฐานจะใช้งานได้หาก$sไม่มีอักขระขึ้นบรรทัดใหม่

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


6

ดังที่คุณได้กล่าวไว้ว่าคุณต้องการกำหนดค่าให้กับidและสตริง

ก่อนกำหนดรูปแบบของคุณให้กับตัวแปร (พูด str)

    str='id;some text here with possible ; inside'
    id=${str%%;} 
    string=${str#;}

ตอนนี้คุณมีค่าของคุณในตัวแปรที่เกี่ยวข้อง


หากคุณได้รับรูปแบบของคุณจากคำสั่งให้ใช้ set - some_commandดังนั้นรูปแบบของคุณจะถูกเก็บไว้ใน $ 1 และใช้รหัสด้านบนด้วย 1 แทน str
user1678213

คำตอบนี้แตกต่างจาก @StephaneChazelas อย่างไร
แบร์นฮาร์ด

4

นอกเหนือจากการแก้ปัญหาอื่น ๆ คุณสามารถลองทำregexตาม:

a="$(sed 's/;.*//' <<< "$s")"
b="$(sed 's/^[^;]*;//' <<< "$s")"

หรือขึ้นอยู่กับสิ่งที่คุณพยายามทำอย่างแน่นอนคุณสามารถใช้

sed -r 's/^([^;]*);(.*)/\1 ADD THIS TEXT BETWEEN YOUR STRINGS \2/'

โดยที่\1และ\2มีสตริงย่อยสองรายการที่คุณต้องการ


1

โซลูชันใน bash มาตรฐาน:

    text='id;some text here with possible ; inside'
    text2=${text#*;}
    text1=${text%"$text2"}

    echo $text1
    #=> id;
    echo $text2
    #=> some text here with possible ; insideDD
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.