วิธีที่ดีกว่าในการทำ“ echo $ x | sed …” และ“ echo $ x | grep …”


14

ฉันมักจะพบสิ่งนี้ในสคริปต์ (และฉันต้องยอมรับเขียนด้วยตัวเอง):

a=$(echo "$x" | sed "s/foo/bar/")

หรือ

if echo "$x" | grep -q foo
then
    ...
fi

พิจารณา "foo" เพื่อรวมบางสิ่งที่ regex

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

ฉันหามันไม่เจอ ใคร?


ฉันคาดหวังว่าการแสดงออกนี้จะใช้บ่อยเนื่องจากการผสมผสานของความไม่รู้ (ไม่รู้ทางเลือก) และการบำรุงรักษา (การรู้ทางเลือก แต่เลือกสิ่งนี้ว่าง่ายกว่าที่จะเข้าใจ) ฉันสามารถบอกได้ทันทีว่าตัวอย่างของคุณทำอะไร แต่ฉันต้องการการอ้างอิงเชลล์เพื่อหาทางเลือกในคำตอบของ grawity และ Dan McG
ต้มตุ๋น quixote

3
โดยวิธีการวิธีที่ต้องการในการทำการทดแทนคำสั่งอยู่ด้วย$()มากกว่า backticks
หยุดชั่วคราวจนกว่าจะมีการแจ้งให้ทราบต่อไป

2
นอกจากนี้ยังเป็นความคิดที่ดีที่จะขยายอ้างเพื่อให้ช่องว่างที่มีการป้องกัน: และa="$(echo "$x" | sed "s/foo/bar/")" if echo "$x" | grep foo; …
Chris Johnsen

ข้อสังเกตที่ดีเกี่ยวกับ $ () เทียบกับ `` ฉันเห็นว่าทักษะการทุบตีของฉันยังไม่ดีนัก
DevSolar

คำตอบ:


12

ถ้าคุณไม่ถือว่าเชลล์ที่เจาะจงไม่มีวิธีที่ดีกว่าในการทำเช่นนี้กว่า "ไปป์สะท้อนไปที่เครื่องมือ" (หรือเพียงแค่ "เครื่องมือ" ตัวเองเช่นexpr ) มันเป็นสิ่งที่คุณจริงๆสามารถนับบนกับแบบดั้งเดิมเปลือกบอร์นและ / หรือPOSIX เปลือก หากคุณพิจารณากระสุนอื่น ๆ แสดงว่ามีความเป็นไปได้อื่น ๆ

kshมี

  • รูปแบบพิเศษ: ?(pattern-list), *(pattern-list), {n}(pattern-list), {n,m}(pattern-list), @(pattern-list), !(pattern-list);
  • ตัวระบุ%P printfเพื่อแปลงนิพจน์ปกติที่ขยายเป็นรูปแบบ (และ%Rสำหรับนิพจน์ทั่วไปที่ขยายเป็นรูปแบบ)
  • expr == patternเงื่อนไขใน[[ expr ]]การทดสอบ;
  • การ${param/pattern/replacement}ขยายพารามิเตอร์

ทุบตีมี

  • extglobตัวเลือกที่จะเปิดใช้งานมากที่สุดของรูปแบบพิเศษของการksh (ไม่{n}และ{n,m});
  • expr == patternสภาพ (ใน[[ expr ]]การทดสอบ);
  • การ${param/pattern/replacement}ขยายพารามิเตอร์
  • (ในเวอร์ชันใหม่กว่า) expr =~ extregexpเงื่อนไข (ใน[[ expr ]]การทดสอบ) ที่สามารถจับคู่กับนิพจน์ทั่วไปที่ขยาย
    • ด้วยนิพจน์ย่อยที่ถูกวงเล็บและBASH_REMATCHพารามิเตอร์สามารถทำการแทนที่สไตล์sedได้

zshมี

  • รูปแบบการขยายของตัวเองพร้อมEXTENDED_GLOBตัวเลือก;
  • ksh-เหมือนรูปแบบเพิ่มเติมพร้อมกับKSH_GLOBตัวเลือก;
  • expr == patternสภาพ (ใน[[ expr ]]การทดสอบ);
  • การ${pattern/pattern/replacement}ขยายพารามิเตอร์
  • expr =~ extregexpสภาพ (ใน[[ expr ]]การทดสอบ) ที่สามารถจับคู่กับการแสดงออกปกติขยาย
    • มันสามารถใช้PCREแทนนิพจน์ปกติแบบขยายธรรมดาหากตั้งค่าตัวเลือก RE_MATCH_PCRE
    • ด้วยนิพจน์ย่อยที่ถูกวงเล็บMATCHพารามิเตอร์และmatchพารามิเตอร์ (หรือBASH_REMATCHด้วยBASH_REMATCHชุดตัวเลือก) สามารถทำการแทนที่แบบsed- style;
  • zsh/pcreโมดูลที่ข้อเสนอpcre_compile, pcre_studyและpcre_matchคำสั่งและ-pcre-match การทดสอบสภาพ (ใน[[ expr ]]การทดสอบ);
  • zsh/regexโมดูลที่มี-regex-match การทดสอบสภาพ (ใน[[ expr ]]การทดสอบ)

ว้าว. เสร็จสมบูรณ์อย่างที่ใคร ๆ ก็ปรารถนา ผู้ชนะอย่างแน่นอน
DevSolar

6

หากต้องการแทนที่สาย sed ทำสิ่งที่ต้องการ

${a/foo/bar} หรือ ${a//foo/bar}

ในฟอร์มแรกเฉพาะอินสแตนซ์แรกเท่านั้นที่ถูกแทนที่ รูปแบบที่สองคือการค้นหาทั่วโลก & แทนที่

ในกรณีของคุณมันจะเป็น

แทน:

if echo $x | grep foo
then
    ...
fi

พิจารณาใช้:

if [ $x =~ foo ]
then
    ...
fi

ที่ไหนfooคือการแสดงออกปกติ


เชลล์นี้ใช้งานอะไรได้บ้าง?
Peltier

1
if [ $x =~ foo ]ให้ข้อความแสดงข้อผิดพลาดที่นี่ if [[ $x =~ foo ]]อย่างไรก็ตามใช้งานได้ดี ขอบคุณ!
DevSolar

1
ทั้งหมดเหล่านี้เป็น bashisms พวกเขาต้องการ bash นอกจากนี้=~ต้องใช้ bash> = 3 iirc
inkaphink

1
Iirc ยัง foo ไม่ใช่นิพจน์ทั่วไป (เหมือนใน PCRE) ในตัวอย่างเหล่านี้ แต่ใช้อักขระตัวแทน มีความนิยมในการทุบตีมากกว่านี้ใน manpage ของ bash ส่วน "การขยายพารามิเตอร์" โดยเฉพาะอย่างยิ่งผมชื่นชมสิ่งที่ต้องการและ${a##foo} ${a%%bar}
inkaphink

3
ตัวดำเนินการจับคู่=~ใช้นิพจน์ทั่วไป สิ่งนี้เป็นจริงตัวอย่างเช่น: [[ "abcdddde" =~ ^a.*d+.g* ]](นั่นคือกรัมหรือมากกว่าของ g แทนที่จะเป็น g-wildcard เป็นต้น)
หยุดชั่วคราวจนกว่าจะมีการแจ้งให้ทราบต่อไป

2

วิธีที่เข้ากันได้กับ posix ที่ดีสำหรับการทดสอบว่าตัวแปรมีรูปแบบหรือไม่:

test ${var##*foo*} || <do something>;

ไวยากรณ์ของการขยายพารามิเตอร์คือ:

 ${parameter##pattern}

ที่patternเป็นรูปแบบเปลือก

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.