แยกสตริงตามรูปแบบในสคริปต์ทุบตี


17

ในทุบตีสมมติว่าฉันมีสตริงstrname:

strname="ph7go04325r"

ฉันต้องการที่จะดึงตัวละครระหว่างครั้งแรก "3"ของตัวละครและสุดท้าย "r"ตัวละครในการประหยัดผลในสตริงstrname strresultในตัวอย่างข้างต้นผลลัพธ์strresultจะเป็น:

strresult="25"

"3"อักขระตัวแรกไม่จำเป็นต้องอยู่ที่ตำแหน่งสตริง 8 ในstrname; เช่นเดียวกันที่ผ่านมา"r"คือไม่จำเป็นต้องที่ตำแหน่งสตริง 11. ดังนั้นทั้งสองสายดังต่อไปนี้strnameควรผลผลิตstrresult="25":

strname="ph11go04325raa"
strname="325r"
strname="rgo04325raa"

นอกจากนี้ควรผลผลิตstrname=ph12go04330raa"strresult="30"

ฉันยังใหม่กับการเขียนสคริปต์ทุบตีและฉันไม่รู้ว่าจะเริ่มจับคู่รูปแบบสตริงได้อย่างไร คุณมีข้อเสนอแนะใด?

คำตอบ:


28

คุณสามารถใช้ regex ใน bash (3.0 หรือสูงกว่า) เพื่อทำสิ่งนี้:

if [[ $strname =~ 3(.+)r ]]; then
    strresult=${BASH_REMATCH[1]}
else
    echo "unable to parse string $strname"
fi

ในทุบตีกลุ่มการจับภาพจาก regex BASH_REMATCHจะถูกวางไว้ในอาร์เรย์พิเศษ องค์ประกอบ 0 ประกอบด้วยการแข่งขันทั้งหมดและ 1 มีการแข่งขันสำหรับกลุ่มการจับภาพแรก


10

ในshไวยากรณ์มาตรฐาน(ดังนั้นจะทำงานกับรุ่นใด ๆ ของbashหรือตาม POSIX เชลล์อื่น ๆ ) คุณจะทำ:

case $strname in
  (*3*r*) 
    strresult=${strname#*3}
    strresult=${strresult%r*};;
  (*)
    printf >&2 '%s\n' "Unable to parse string $strname"
esac

ดูexprวิธีแก้ปัญหาแบบเก่าซึ่งจะใช้กับ Unices ที่มีอายุ 35 ปีด้วย:

expr "x$strname" : 'x[^3]*3\(.*\)r'

มุมแหลมเก่าด้วยexprคือถ้าการจับคู่ล้มเหลวคุณจะได้รับสถานะทางออกไม่เป็นศูนย์ (ดี) แต่คุณยังได้รับสถานะทางออกที่ไม่เป็นศูนย์ด้วยถ้าสตริงที่ส่งคืนแก้ไขเป็น 0 (เช่นเดียวกับstrname=zz300rzz)


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

1
@kojiro ฉันเห็นสิ่งที่คุณหมายถึง สูตรเริ่มต้นคือการติดตามผลคำตอบของจอร์แดน ฉันอัพเดตคำตอบแล้ว
Stéphane Chazelas
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.