การทดสอบ Bash:“ = ~” ทำอะไร


39
#!/bin/bash
INT=-5

if [[ "$INT" =~ ^-?[0-9]+$ ]]; then

echo "INT is an integer."

else

echo "INT is not an integer." >&2

exit 1

fi

ผู้นำ~ทำอะไรในการแสดงออกปกติเริ่มต้น?



5
คุณอ่านคู่มือทุบตีแล้วหรือยัง? คุณพบอะไรที่ไม่ชัดเจน
รัส

3
ค้นหาหน้า bash man สำหรับ = ~
Jeff Schaller

คำตอบ:


46

~เป็นจริงส่วนหนึ่งของผู้ประกอบการ=~ที่มีประสิทธิภาพการแข่งขันการแสดงออกปกติของสตริงไปซ้ายเพื่อการแสดงออกปกติขยายทางด้านขวา

[[ "string" =~ pattern ]]

โปรดทราบว่าสตริงควรถูกยกมาและนิพจน์ปกติไม่ควรยกมา

ตัวดำเนินการที่คล้ายกันถูกใช้ในภาษาการเขียนโปรแกรม Perl

นิพจน์ทั่วไปที่เข้าใจbashจะเหมือนกับนิพจน์ที่ GNU grepเข้าใจกับ-Eธงนั่นคือชุดของนิพจน์ทั่วไป


ค่อนข้างปิดหัวข้อ แต่ก็ควรรู้:

เมื่อจับคู่กับนิพจน์ทั่วไปที่มีกลุ่มการจับภาพส่วนของสตริงที่จับโดยแต่ละกลุ่มจะมีอยู่ในBASH_REMATCHอาร์เรย์ ข้อที่ศูนย์ / รายการแรกในสอดคล้องกับอาร์เรย์นี้&ในรูปแบบการเปลี่ยนsedของคำสั่งเปลี่ยนตัว (หรือ$&ใน Perl) ซึ่งเป็นบิตของสตริงที่ตรงกับรูปแบบในขณะที่รายการที่ดัชนีที่ 1 และเป็นต้นไปสอดคล้องกับ\1, \2ฯลฯ . ในsedรูปแบบการเปลี่ยน (หรือ$1, $2ฯลฯ ใน Perl) คือบิตจับคู่โดยแต่ละวงเล็บ

ตัวอย่าง:

string=$( date +%T )

if [[ "$string" =~ ^([0-9][0-9]):([0-9][0-9]):([0-9][0-9])$ ]]; then
  printf 'Got %s, %s and %s\n' \
    "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}" "${BASH_REMATCH[3]}"
fi

สิ่งนี้อาจส่งออก

Got 09, 19 and 14

หากเวลาปัจจุบันเกิดขึ้นเป็น 09:19:14

REMATCHบิตBASH_REMATCHarray ชื่อที่มาจากการ "จับคู่นิพจน์ทั่วไป" คือ "RE-Match"


ในbashเชลล์ที่ไม่คล้ายบอร์นหนึ่งอาจใช้exprสำหรับการจับคู่นิพจน์ทั่วไปที่ จำกัด (ใช้เฉพาะนิพจน์ปกติพื้นฐาน)

ตัวอย่างเล็ก ๆ :

$ string="hello 123 world"
$ expr "$string" : ".*[^0-9]\([0-9][0-9]*\)"
123

2
มันเหมือนกับสิ่งที่grep -Eเข้าใจเฉพาะในระบบ GNU และเฉพาะเมื่อใช้ตัวแปรที่ไม่มีเครื่องหมายเป็นรูปแบบ[[ $var = $pattern ]](ดู[[ 'a b' =~ a\sb ]]vs p='a\sb'; [[ 'a b' =~ $p ]]) นอกจากนี้ระวังว่าการอ้างเชลล์มีผลต่อความหมายของตัวดำเนินการ RE และอักขระบางตัวจำเป็นต้องอ้างถึงสำหรับโทเค็นเชลล์ที่อาจส่งผลกระทบต่อการประมวลผล RE [[ '\' =~ [\/] ]]ผลตอบแทนที่เป็นเท็จ ksh93มีปัญหาที่เลวร้ายยิ่งกว่า ดูzsh(หรือทุบตี 3.1) สำหรับแนวทาง saner ที่เชลล์และการอ้างอิง RE แตกต่างกัน ใน[ตัวzshและyashยังมี=~ผู้ประกอบการ
Stéphane Chazelas

2
เด็ดมากoff-topic! +1 (
JJoao

@ StéphaneChazelasมันเป็นวิธีการ "มั่นคง" ว่าทั้งสองของการแข่งขันครั้งนี้ใน [[ "This is a fine mess." =~ T.........fin*es* ]]; [[ "This is a fine mess." =~ T.........fin\*es\* ]]zsh หรือว่าการเสนอราคา*ยังตรงกับ? [[ "This is a fine mess." =~ "T.........fin*es*" ]].
sorontar

มันคือ saner (IMO) เพราะมันเป็นกฎที่ง่ายกว่ามาก การอ้างอิงเชลล์และการหลบหนี RE นั้นแยกจากกันอย่างชัดเจน ใน[[ a =~ .* ]]หรือ[[ a =~ '.*' ]]หรือRE [[ a =~ \.\* ]]เดียวกัน.*ถูกส่งผ่านไปยัง=~ผู้ประกอบการ OTH ในbash, [[ '\' =~ [)] ]]ผลตอบแทนข้อผิดพลาดคุณจะได้รู้โดยไม่ต้องพยายามมันไม่ว่าจะเป็น[[ '\' =~ [\)] ]]แมตช์? วิธีการเกี่ยวกับ[[ '\' =~ [\/] ]](มันเป็น ksh93) วิธีการเกี่ยวกับc='a-z'; [[ a =~ ["$c"] ]](เปรียบเทียบกับ=ผู้ประกอบการ)? ดูเพิ่มเติม: [[ '\' =~ [^]"."] ]]ซึ่งจะส่งกลับเท็จ ... โปรดทราบว่าคุณสามารถทำได้shopt -s compat31ในการbashที่จะได้รับzshพฤติกรรม
Stéphane Chazelas

zsh/ bash -o compat31พฤติกรรมสำหรับ[[ a =~ '.*' ]]ยังสอดคล้องกับ[ a '=~' '.*' ](สำหรับ[การใช้งานที่สนับสนุน=~) expr a : '.*'หรือ OTOH ไม่สอดคล้องกับ[[ a = '*' ]]vs [[ a = * ]](แต่แล้ว globs เป็นส่วนหนึ่งของภาษาเชลล์ในขณะที่ RE ไม่ได้เป็น)
Stéphane Chazelas

4

คุณควรอ่าน bash man pages ภายใต้[[ expression ]]หัวข้อ

An additional binary operator, =~, is available, with the same precedence as == and !=. When it is used, the string to the right of the operator is considered an extended regular expression and matched accordingly (as in regex(3)).

เรื่องยาวสั้น, =~เป็นผู้ดำเนินการเช่นเดียวกับและ== !=มันไม่มีส่วนเกี่ยวข้องกับ regex จริงในสตริงทางด้านขวา


คุณลองนึกภาพตัวอย่างที่แสดงให้เห็นถึงการใช้งาน=~ในชีวิตจริง ... ?
George Vasiliou

1
@GeorgeVasiliou ฉันใช้มันค่อนข้างบ่อยในสคริปต์ที่ทำให้เอาต์พุตจากคำสั่งเป็นตัวแปร จากนั้นตัวแปรจะถูกตรวจสอบเพื่อดูว่าตรงกับรูปแบบสตริงบางอย่างหรือไม่ สิ่งนี้มีประโยชน์เช่นถ้าคุณต้องการดำเนินการบางอย่างโดยอิงตามข้อผิดพลาดบางส่วนจากคำสั่งนั้น
Michael Martinez

@Sokel สำหรับบางคน“ RTFM” พูดง่ายกว่าทำ ⋯ man [[ expresssion ]]และman [[ไม่คืนสิ่งใด help [[ส่งคืนข้อมูลที่เป็นประโยชน์ตั้งแต่[[คำสั่ง bash ภายใน แต่ไม่ได้บอกว่าจะ=~ใช้ไวยากรณ์พื้นฐานหรือขยาย regex ⋯ข้อความที่คุณยกมานั้นมาจากหน้าbash man ฉันรู้ว่าคุณพูดว่า "อ่านหน้าคนทุบตี" แต่ตอนแรกฉันคิดว่าคุณหมายถึงอ่านหน้าคนที่อยู่ในทุบตี ให้man bashส่งคืนไฟล์ขนาดใหญ่ที่มีความยาว 4139 บรรทัด (72 หน้า) สามารถค้นหาได้โดยกด/▒▒▒ซึ่งใช้ regex รสชาติที่=~ไม่เหมือนที่ระบุ
Alex Quinn
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.