ทำไม xargs ตัดเครื่องหมายคำพูดออกจากอินพุต


25

ทำไม xargs ตัดเครื่องหมายคำพูดออกจากข้อความอินพุต

นี่คือตัวอย่างง่าย ๆ :

echo "/Place/='http://www.google.com'" | xargs echo

เอาท์พุท

/Place/=http://www.google.com

มีวิธีการแก้ไขปัญหานี้หรือไม่? (xargs -0 ไม่ช่วยฉัน)


1
xargsคำพูดถือว่าและเครื่องหมายพิเศษเป็นส่วนหนึ่งของข้อมูลจำเพาะ โพสต์สิ่งที่คุณพยายามทำxargsแทน
jw013

3
xargs -0ได้ผลสำหรับฉันที่นี่ ... ทำไมจึงไม่ช่วยคุณ
Derobert

คำตอบ:


10

จากxargsคู่มือ:

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

ซึ่งหมายความว่าคุณสามารถหลีกเลี่ยงคำพูดได้ถ้าคำพูดที่ยกมาตัวเอง:

$ echo "/Place/=\'http://www.google.com\'" | xargs echo
/Place/='http://www.google.com'

จะทำงาน แต่echo /Place/=\'http://www.google.com\' | xargs echoจะไม่


1
ไม่มีอะไรกับการลงคะแนนเสียง แต่ความคิดเห็นเกี่ยวกับเหตุผลที่จะช่วย :-)
มัตเตโอ

3
เกิดอะไรขึ้นถ้าคุณกำลังป้อนข้อมูลในท่อ? หากฉันมีสคริปต์ที่เอาต์พุต"/Place/='http://www.google.com'"ฉันจะหนีได้อย่างถูกต้องได้อย่างไร?
Roger Filmyer

1
@RogerFilmyer your_script | ขนาน - shellquote | ...
Ole Tange

19

ถ้าคุณต้องการxargsที่จะไม่สนใจคำพูดหนึ่งใน soultion ดีสามารถใช้xargsธงxargs -0

โดยตรงจากตัวเลือกหน้าคน

ตัวเลือก -0, - เป็นศูนย์

ไอเท็มอินพุตถูกยกเลิกด้วยอักขระ null แทนช่องว่างและเครื่องหมายคำพูดและแบ็กสแลชไม่ได้เป็นพิเศษ (ทุกตัวอักษรถูกใช้อย่างแท้จริง) ปิดใช้งานจุดสิ้นสุดไฟล์สตริงซึ่งถือว่าเหมือนกับอาร์กิวเมนต์อื่น ๆ มีประโยชน์เมื่อรายการอินพุตอาจมีช่องว่างเครื่องหมายคำพูดหรือแบ็กสแลช ตัวเลือก GNU find -print0 สร้างการป้อนข้อมูลที่เหมาะสมสำหรับโหมดนี้

ฉันได้ตรวจสอบระบบ GNU ว่าการตั้งค่าตัวคั่นเป็นค่าเฉพาะ (เช่นบรรทัดใหม่) ด้วย-dตัวเลือก (และไม่ใช่แค่-0) จะทำให้xargsไม่รักษาคำพูด ฯลฯ เป็นพิเศษ:

-bash-4.3$ { echo "a'b'c"; echo d; } | xargs -d$'\n' echo
a'b'c d
-bash-4.3$ rpm -qf "$(which xargs)"
findutils-4.6.0.0.99.11a05-alt1.x86_64
-bash-4.3$ { echo "a'b'c"; echo d; } | xargs echo
abc d
-bash-4.3$ 


7

ฉันพบวิธีแก้ไขปัญหาอื่นใน manpage: ระบุตัวคั่นให้เป็น '\ n' อย่างชัดเจน สิ่งนี้จะปิดการจัดการพิเศษสำหรับคำพูด:

--delimiter = delim, -d delim

รายการอินพุตถูกยกเลิกโดยอักขระที่ระบุ ตัวคั่นที่ระบุอาจเป็นอักขระเดียวการยกเว้นอักขระแบบ C เช่น \ n หรือรหัสการออกจากฐานแปดหรือฐานสิบหก รหัสการหลบหนีออกจากฐานแปดและเลขฐานสิบหกนั้นเข้าใจได้สำหรับคำสั่ง printf ไม่รองรับอักขระหลายไบต์ เมื่อประมวลผลอินพุตเครื่องหมายคำพูดและแบ็กสแลชจะไม่พิเศษ อักขระทุกตัวในอินพุตถูกใช้อย่างแท้จริง

ดังนั้น,

echo "/Place/='http://www.google.com'" | xargs -d'\n' echo

เอาท์พุท

/Place/='http://www.google.com'

โปรดทราบว่ามันแสดงถึง GNU xargsหรือ
เทียบเท่า

นอกจากนี้โปรดทราบว่ามันยังหยุดเว้นวรรคและแท็บไม่ให้จำได้ว่าเป็นตัวคั่น (อาจเป็นได้ในกรณีของ OP)
Stéphane Chazelas

Balman ให้โซลูชันที่คล้ายกัน ( จริง ๆ แล้ว @imz ) ถึงแม้ว่าคุณจะค่อนข้างดีกว่าในการหลีกเลี่ยงการใช้ตัวksh93 $'...'ดำเนินการที่ไม่พบในทุกการใช้งานเชลล์
Stéphane Chazelas

4

ฉันพบวิธีแก้ไขปัญหาอื่นที่นี่/programming//a/17468560/1795821ที่แนะนำให้ใช้sedเพื่อหลีกเลี่ยงคำพูด

ตัวอย่างเช่น:

sh-3.2$ echo "/Place/='http://www.google.com'" | sed "s/\'/\\\'/g" | xargs echo
/Place/='http://www.google.com'
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.