ฉันเพียงแค่ต้องได้รับการแข่งขันจากการแสดงออกปกติ:
$ cat myfile.txt | SOMETHING_HERE "/(\w).+/"
ผลลัพธ์จะต้องเป็นสิ่งที่ตรงกันภายในวงเล็บ
อย่าคิดว่าฉันสามารถใช้grep ได้เพราะมันตรงกับทั้งบรรทัด
โปรดแจ้งให้เราทราบวิธีการทำเช่นนี้
ฉันเพียงแค่ต้องได้รับการแข่งขันจากการแสดงออกปกติ:
$ cat myfile.txt | SOMETHING_HERE "/(\w).+/"
ผลลัพธ์จะต้องเป็นสิ่งที่ตรงกันภายในวงเล็บ
อย่าคิดว่าฉันสามารถใช้grep ได้เพราะมันตรงกับทั้งบรรทัด
โปรดแจ้งให้เราทราบวิธีการทำเช่นนี้
คำตอบ:
2 สิ่ง:
-o
ตัวเลือกดังนั้นจะมีการพิมพ์เฉพาะการแข่งขัน (แทนที่จะเป็นทั้งบรรทัด)-P
ตัวเลือกเพื่อใช้การแสดงผลปกติของ Perl ซึ่งรวมถึงองค์ประกอบที่มีประโยชน์เช่นLook forward (?= )
และLook behind (?<= )
ผู้ค้นหาชิ้นส่วน แต่ไม่ตรงกับและพิมพ์จริงหากคุณต้องการให้จับคู่ส่วนใน parensis เท่านั้น:
grep -oP '(?<=\/\()\w(?=\).+\/)' myfile.txt
หากไฟล์มีการต่อย/(a)5667/
grep จะพิมพ์ 'a' เพราะ:
/(
ถูกค้นพบด้วย\/\(
แต่เนื่องจากพวกเขาอยู่ในสภาพที่ดู (?<= )
ไม่ได้รายงานa
จับคู่โดย\w
และถูกพิมพ์ (เนื่องจาก-o
))5667/
พบ b < \).+\/
แต่เนื่องจากอยู่ในรูปลักษณ์ล่วงหน้า (?= )
จึงไม่มีการรายงานใช้ตัวเลือกใน-o
grep
เช่น:
$ echo "foobarbaz" | grep -o 'b[aeiou]r'
bar
sed -n "s/^.*\(captureThis\).*$/\1/p"
-n don't print lines
s substitute
^.* matches anything before the captureThis
\( \) capture everything between and assign it to \1
.*$ matches anything after the captureThis
\1 replace everything with captureThis
p print it
หากคุณต้องการเฉพาะสิ่งที่อยู่ในวงเล็บคุณต้องการสิ่งที่รองรับการจับคู่ย่อย (กลุ่มที่มีชื่อหรือกลุ่มการจับหมายเลข) ฉันไม่คิดว่า grep หรือ egrep สามารถทำสิ่งนี้ได้ Perl และ sed สามารถ ตัวอย่างเช่นด้วย Perl:
หากไฟล์ที่ชื่อว่า foo มีบรรทัดอยู่ดังต่อไปนี้:
/adsdds /
และคุณทำ:
perl -nle 'print $1 if /\/(\w).+\//' foo
จดหมาย a ถูกส่งคืน นั่นอาจไม่ใช่สิ่งที่คุณต้องการ หากคุณบอกเราว่าคุณพยายามจับคู่อะไรคุณอาจได้รับความช่วยเหลือที่ดีกว่า $ 1 คือทุกอย่างที่อยู่ในวงเล็บชุดแรก $ 2 จะเป็นชุดที่สองเป็นต้น
เนื่องจากคุณแท็กคำถามของคุณเป็นทุบตีนอกเหนือจากเชลล์แล้วยังมีวิธีแก้ไขอื่นนอกเหนือจากgrep :
Bash มีเอ็นจิ้นนิพจน์ปกติของตัวเองตั้งแต่เวอร์ชัน 3.0 โดยใช้=~
โอเปอเรเตอร์เหมือนกับ Perl
ตอนนี้ได้รับรหัสต่อไปนี้:
#!/bin/bash
DATA="test <Lane>8</Lane>"
if [[ "$DATA" =~ \<Lane\>([[:digit:]]+)\<\/Lane\> ]]; then
echo $BASH_REMATCH
echo ${BASH_REMATCH[1]}
fi
bash
ไม่ใช่sh
เพื่อรับส่วนขยายทั้งหมด$BASH_REMATCH
จะให้สตริงทั้งหมดตามที่จับคู่โดยนิพจน์ทั่วไปทั้งหมดดังนั้น <Lane>8</Lane>
${BASH_REMATCH[1]}
จะให้ส่วนที่ตรงกับกลุ่มที่ 1 ดังนั้นเท่านั้น 8
>
สัญลักษณ์เพื่อจุดประสงค์ที่แตกต่างกันอย่างสิ้นเชิง) ดังที่ได้กล่าวโดยซอฟต์แวร์จัดตำแหน่ง SANSparallelเร็วขนาดใหญ่ แน่นอนว่าทั้งสองรูปแบบถูกสอดประสานเข้าด้วยกันโดยไม่มีการหลบหนีใด ๆ ดังนั้นจึงเป็นไปไม่ได้ที่จะโยนไลบรารี่ XML มาตรฐานนี้ และฉันใช้ Bash regex ณ จุดนี้ของรหัสเพราะฉันต้องการเพียงดึงข้อมูลสองสามชุดและ 2 regex ทำงานให้ฉันได้ดีกว่าการเขียน parser เฉพาะสำหรับระเบียบนี้ #LifeInBioinformatics
สมมติว่าไฟล์มี:
$ cat file
Text-here>xyz</more text
และคุณต้องการอักขระระหว่าง>
และ</
คุณสามารถใช้:
grep grep -oP '.*\K(?<=>)\w+(?=<\/)' file
sed sed -nE 's:^.*>(\w+)</.*$:\1:p' file
awk awk '{print(gensub("^.*>(\\w+)</.*$","\\1","g"))}' file
perl perl -nle 'print $1 if />(\w+)<\//' file
ทั้งหมดจะพิมพ์สตริง "xyz"
หากคุณต้องการจับตัวเลขของบรรทัดนี้:
$ cat file
Text-<here>1234</text>-ends
grep grep -oP '.*\K(?<=>)[0-9]+(?=<\/)' file
sed sed -E 's:^.*>([0-9]+)</.*$:\1:' file
awk awk '{print(gensub(".*>([0-9]+)</.*","\\1","g"))}' file
perl perl -nle 'print $1 if />([0-9]+)<\//' file
echo 'Text-<here>1234</text>-ends' | sed -E 's|.*>([[:digit:]]+)<.*|\1|'
ทำ: ในบางกรณี (เช่น[0-9]
กับ[[:digit:]]
) พวกเขาไม่ได้ช่วยให้อ่านง่ายขึ้นในบางกรณีฉันคิดว่าพวกเขาทำ (เช่น[ \t\n\r\f\v]
กับ[:space:]
)
สิ่งนี้จะบรรลุสิ่งที่คุณร้องขอ แต่ฉันไม่คิดว่ามันเป็นสิ่งที่คุณต้องการจริงๆ ฉันวาง.*
ด้านหน้าของ regex เพื่อกินอะไรก่อนการแข่งขัน แต่นั่นเป็นการดำเนินการโลภดังนั้นนี่ตรงกับ\w
ตัวละครสุดท้ายในสตริง
โปรดทราบว่าคุณต้องการที่จะหลบหนี parens +
และ
sed 's/.*\(\w\).\+/\1/' myfile.txt
sed
backreferences ที่จะทำเช่นนั้น?