คำสั่งการแทนที่ 'sed' นี้ที่มีเครื่องหมาย @ จำนวนมากทำงานอย่างไร


8

ใครสามารถอธิบายวิธีการsedทำงานของคำสั่งนี้

sed 's@+@ @g;s@%@\\x@g' | xargs -0 printf "%b"

3
วิธีปกติในการทำเช่นนี้คือการใช้เครื่องหมายทับ (slash) แต่อาจจะยุ่งยากหากคุณค้นหาและแทนที่ด้วยเครื่องหมายทับ นี่ไม่ใช่กรณีที่นี่ดังนั้นแม้ว่ามันจะเป็นเรื่องที่สมบูรณ์แบบ แต่ก็ยังสร้างความสับสนให้กับผู้ดูแลในอนาคตเช่นคุณ
Thorbjørn Ravn Andersen

2
…และพาพวกเขาไปเรียนรู้สิ่งใหม่เกี่ยวกับsedวิธีนี้! :)
ของหวาน

คำตอบ:


15

ใน sed s/pattern/replacement/optionsคำสั่งแทนมักจะเขียนเป็น แต่ก็ไม่จำเป็นต้องใช้/- คุณสามารถใช้ตัวละครอื่น ๆ ถ้ามันเป็นความสะดวกสบายดังนั้นมันอาจจะเป็นหรือs@pattern@replacement@options เป็นเหมือน- แทนที่ทั้งหมดด้วยช่องว่าง ในทำนองเดียวกันแทนที่ทั้งหมดด้วย(แบ็กสแลชเดี่ยวคืออักขระ escape ใน sed ดังนั้นคุณต้องมีสองสแลชเพื่อรับแบ็กสแลชจริง)s:foo:bar:gs@+@ @gs/+/ /g+s@%@\\x@g%\x

สตริงเช่นนั้นจะกลายเป็นfoo+%2Fbar จะขยายลำดับหนีแบคสแลชเช่น(อักขระ ASCII ที่มีค่าเลขฐานสิบหกเป็น 2F ซึ่งก็คือ) เพื่อให้คุณได้ในที่สุดfoo \x2Fbarprintf "%b"\x2F/foo /bar


2
โดยย่อตัวถอดรหัส URL-> ชื่อไฟล์
Thorbjørn Ravn Andersen

10

คำสั่งที่คุณถามเกี่ยวกับการถอดรหัส+es และ%ลำดับจาก URLไม่ใช่sedคำสั่งมันเป็นไพพ์ไลน์ที่ประมวลผลอินพุตsedจากนั้นไพพ์ไปยังxargsเพื่อการประมวลผลเพิ่มเติม ก่อนอื่นให้ดูที่sedคำสั่ง:

sed 's@+@ @g;s@%@\\x@g'

คุณอาจคุ้นเคยกับการเห็น/มากกว่า@ตัวคั่นซึ่งทำได้ง่าย ๆ โดยไม่มีความยุ่งยากเนื่องจาก/ปรากฏในรูปแบบการค้นหาหรือข้อความทดแทนใด ๆ คำสั่งนี้เทียบเท่า:

sed 's/+/ /g;s/%/\\x/g'

ชอบ/, เป็นตัวละครที่เครื่องหมายวรรคตอนที่ดีที่ดีเลิศสำหรับ@sed

ในแต่ละบรรทัดอินพุต:

  1. s@+@ @g( s/+/ /g) ทดแทน ( s) การเกิดขึ้นของ+ด้วยช่องว่าง สิ่งนี้มีผลต่อ+es ทั้งหมดในบรรทัด ( g) ไม่ใช่แค่อันแรก

  2. ; สิ้นสุดการกระทำ ("คำสั่ง") และช่วยให้คุณสามารถระบุการกระทำอื่นใน "สคริปต์เดียวกัน"

  3. s@%@\\x@g( s/%/\\x/g) ทดแทน ( s) การเกิดขึ้นของด้วย% \xเหมือนก่อนหน้านี้มันทำงานได้ทั้งหมดมากกว่าแค่แค่บรรทัดแรกของแต่ละบรรทัด ( g)

    ในเป็นตัวแทนเพียงหนึ่งเพราะมีความหมายพิเศษเพื่อ ความหมายพิเศษของมันนั้นจริง ๆ แล้วเป็นตัวละครที่คุณใช้เพื่อกำจัดความหมายพิเศษของตัวละครอื่นที่ตามมาซึ่งจะมีความหมายพิเศษเป็นอย่างอื่น ดังนั้นจึงต้องหนีออกมาเป็น\\x\\\\sed\\


ตอนนี้ให้ดูที่คำสั่งที่มีวัตถุประสงค์คือการทำงานxargsprintf

xargsสร้างบรรทัดคำสั่ง หากคุณเรียกใช้โดยที่หนึ่งคำหรือมากกว่านั้นจะทำงานโดยมีอาร์กิวเมนต์บรรทัดคำสั่งเพิ่มเติมอ่านจากอินพุต ในกรณีนี้อินพุตเป็นเอาต์พุตของเนื่องจาก pipe ( ) โดยปกติจะตีความช่องว่างใด ๆ ในอินพุตเพื่อแปลว่าข้อความก่อนและหลังถือว่าเป็นอาร์กิวเมนต์แยกต่างหาก แต่ตัวเลือกทำให้แยกอาร์กิวเมนต์ที่เกิดขึ้นของอักขระ nullแทนxargs command...command...xargscommand...xargssed|xargs-0

ในการใช้คำสั่งของคุณอย่างตั้งใจอักขระ null จะไม่ปรากฏขึ้นและxargsจะทำงานprintf %bโดยมีอาร์กิวเมนต์บรรทัดคำสั่งเพิ่มเติมเพียงหนึ่งเอาต์พุตของsedคำสั่ง ดังนั้นในขณะที่ไม่เทียบเท่ากันโดยทั่วไปในกรณีนี้ไพพ์ไลน์ทั้งหมดอาจถูกเขียนแทนเช่นนี้โดยใช้การทดแทนคำสั่งแทนxargs:

printf '%b\n' "$(sed 's/+/ /g;s/%/\\x/g')"

สำหรับสิ่งที่printfตั้งใจจะทำที่นี่เช่นเดียวกับที่ muru บอกว่าตัว%bระบุรูปแบบจะใช้และพิมพ์อาร์กิวเมนต์ (เช่น%s) แต่ทำให้แบ็กสแลชหนี - จากการเรียงลำดับsedคำสั่งทางด้านซ้ายของไพพ์ถูกเขียนขึ้นเพื่อสร้าง - เพื่อแปล เป็นตัวอักษรพวกเขาเป็นตัวแทน

สมมติว่าฉันใช้คำสั่งนั้นและส่งผ่านhttp://foldoc.org/debugging%20by%20printfเป็นอินพุต ฉันได้รับhttp://foldoc.org/debugging by printfเป็นผลลัพธ์เนื่องจาก%20ลำดับถูกแปลเป็นช่องว่าง


3

นั่นคือความงามของsedมันใช้กระบวนทัศน์ของตัวเอง ... หลังจากคำสั่ง (เช่นsหรือtrหรือไม่มีอะไร) ตัวละครต่อไปถือว่าเป็นตัวแยก

คุณควรเลือกอย่างชาญฉลาดเพื่อหลีกเลี่ยงการรบกวนกับเชลล์และคำสั่งเองและรักษาสิ่งที่สามารถอ่านได้ แต่มันก็ใช้ได้อย่างสมบูรณ์แบบที่จะเขียนสิ่งที่น่ากลัวอย่างเช่น:

echo 'arrival' | sed srarbrg

... และรับbrrivblผลซึ่งเป็นสิ่งที่คุณคาดหวัง คุณสามารถสนุกไปกับการทำให้เป็นความลับได้เช่นใน:

echo 'arrival' | sed s\fa\fb\fg   # \f is form feed, chr(12)

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

เพียงจำไว้ว่าเป้าหมายคือการทำให้สิ่งต่าง ๆ ง่ายขึ้นไม่เป็นความลับ


ทำงานด้วยแนวคิดที่ซ่อนเร้นนี่เป็นคำสั่ง sed ที่ถูกต้องแม้ว่ามันจะไม่ทำสิ่งใดที่มีประโยชน์:sed "snack is an apple or something" <<< "I sed your snack is an apple or something"
wjandrea

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