กลุ่มจับภาพไม่ทำงาน


27

[0-9]+\.[0-9]+\.[0-9]ฉันมีสตริงของรูปแบบที่ ฉันต้องการแยกตัวเลขตัวแรกตัวที่สองและที่สามแยกจากกัน ตามที่ฉันเข้าใจแล้วกลุ่มการจับกุมควรมีความสามารถในเรื่องนี้ ฉันควรจะสามารถใช้sed "s/\([0-9]*\)/\1/gเพื่อรับหมายเลขแรกsed "s/\([0-9]*\)/\2/gรับหมายเลขที่สองและsed "s/\([0-9]*\)/\3/gเพื่อรับหมายเลขที่สาม ในแต่ละกรณีฉันได้รับข้อความทั้งหมด ทำไมสิ่งนี้จึงเกิดขึ้น


6
กลุ่มการจับภาพจับทั้งกลุ่ม ... ไม่ใช่องค์ประกอบแต่ละรายการในกลุ่ม คุณต้องการบางสิ่งเช่น's/\([0-9]\)\([0-9]\)\([0-9]\).*/\1\2\3/'จับภาพหมายเลขบุคคล
มูนีร์

คำตอบ:


45

เราไม่สามารถให้คำตอบแบบเต็มโดยไม่มีตัวอย่างการป้อนข้อมูลของคุณ แต่ฉันสามารถบอกคุณได้ว่าการเข้าใจกลุ่มจับภาพของคุณนั้นผิด คุณไม่ได้ใช้มันอย่างต่อเนื่องพวกเขาอ้างถึง regex ทางด้านซ้ายมือของโอเปอเรเตอร์การเปลี่ยนตัวเดียวกัน ถ้าคุณจับภาพเช่น/(foo)(bar)(baz)/นั้นfooจะ\1, barจะเป็น\2และจะเป็นbaz \3คุณไม่สามารถทำได้s/(foo)/\1/; s/(bar)/\2/เพราะในการs///โทรครั้งที่สองมีกลุ่มที่ถูกจับได้เพียงกลุ่มเดียวดังนั้น\2จะไม่ถูกกำหนด

ดังนั้นหากต้องการจับตัวเลขสามกลุ่มคุณจะต้อง:

sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\1 : \2 : \3/'

หรือยิ่งอ่านได้มากขึ้น:

sed -E 's/([0-9]*)\.([0-9]*)\.([0-9]*)/\1 : \2 : \3/'

1
ประโยชน์ของการหลีกเลี่ยงวงเล็บในตัวอย่างแรกคืออะไร
Josh M.

2
@JoshM คุณต้องหลบหนีพวกเขาเพื่อที่พวกเขาจะสามารถใช้ในการจับรูปแบบ โดยปกติ/(foo)/ใน sed จะตรงกับตัวอักษร(ตัวอักษรตามด้วยแล้วตัวอักษรfoo )หากคุณต้องการจับภาพกลุ่มคุณจะต้องหลีกเลี่ยงวงเล็บหรือใช้-Eตัวเลือก
terdon

ฉันมักจะใช้-rธงดังนั้นฉันคิดว่านั่นเป็นสาเหตุที่ฉันยังไม่พบสิ่งนี้
Josh M.

1
@JoshM ใช่-rธงจะทำเช่นนั้น แต่ไม่สามารถพกพาได้ GNU sed สนับสนุนมัน แต่คนอื่น ๆ ทำไม่ได้ -Eเป็นสากลมากขึ้น
terdon

9

ตัวอย่าง:

$ echo "123.456.78" |sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\1/'
123

$ echo "123.456.78" |sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\2/'
456

$ echo "123.456.78" |sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\3/'
78

หรือทั้งหมดเข้าด้วยกัน:

$ echo "123.456.78" |sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\1 : \2 : \3/'
123 : 456 : 78

2

ใช้ Sed ด้วย -r, --regexp-extended เพื่อหลีกเลี่ยงวงเล็บที่หนีทั้งหมด

echo "1234.567.89" | sed -r 's/([0-9]+)\.([0-9]+)\.([0-9]+)/\1, \2, \3/' 
1234, 567, 89    #output
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.