ฉันรู้ว่าได้รับl="a b c"
,
echo $l | xargs ls
อัตราผลตอบแทน
ls a b c
ซึ่งสร้างผลผลิต
mycommand -f a -f b -f c
ฉันรู้ว่าได้รับl="a b c"
,
echo $l | xargs ls
อัตราผลตอบแทน
ls a b c
ซึ่งสร้างผลผลิต
mycommand -f a -f b -f c
คำตอบ:
วิธีหนึ่งในการทำ:
echo "a b c" | xargs printf -- '-f %s\n' | xargs mycommand
นี้อนุมานa
, b
และc
ไม่ได้มีช่องว่างการขึ้นบรรทัดใหม่, คำพูดหรือเครื่องหมาย :)
ด้วย GNU findutil
คุณสามารถจัดการกรณีทั่วไป แต่มันซับซ้อนกว่าเล็กน้อย:
echo -n "a|b|c" | tr \| \\0 | xargs -0 printf -- '-f\0%s\0' | xargs -0 mycommand
คุณสามารถแทนที่|
คั่นด้วยตัวอักษรอื่น ๆ บางอย่างที่ไม่ได้ปรากฏในa
, หรือb
c
แก้ไข:เนื่องจาก@MichaelMolบันทึกไว้ด้วยรายการอาร์กิวเมนต์ที่ยาวมากจึงมีความเสี่ยงที่จะเกิดความยาวสูงสุดของอาร์กิวเมนต์ที่สามารถส่งผ่านไปmycommand
ได้ ที่เกิดขึ้นเมื่อที่ผ่านมาxargs
จะแบ่งรายการและเรียกใช้สำเนาของผู้อื่นmycommand
และมีความเสี่ยงของมันออกจาก -f
unterminated หากคุณกังวลเกี่ยวกับสถานการณ์นั้นคุณสามารถเปลี่ยนxargs -0
ข้างต้นด้วยสิ่งนี้:
... | xargs -x -0 mycommand
วิธีนี้จะไม่แก้ปัญหา แต่จะยกเลิกการทำงานmycommand
เมื่อรายการอาร์กิวเมนต์ยาวเกินไป
mycommand
แต่ผมไม่คิดว่าจะมีวิธีใดที่มีความหมายในการจัดการกับสถานการณ์ที่โดยไม่ต้องรู้เพิ่มเติมเกี่ยวกับ คุณสามารถเพิ่ม-x
เป็นครั้งสุดท้ายxargs
ได้เสมอ
xargs
เลยและใช้find
ถ้ามันสามารถใช้ได้ วิธีนี้มีอันตราย อย่างน้อยคุณควรเตือนกรณีที่ล้มเหลวในคำตอบของคุณ
find
จะเป็นคำตอบทั่วไปที่ดีกว่าได้อย่างไรโดยเฉพาะอย่างยิ่งเมื่ออาร์กิวเมนต์เริ่มต้นไม่ใช่ชื่อไฟล์ :)
-f
และด้วยเครื่องมือตัวอย่างที่ls
ใช้สำหรับภาพประกอบ @ not-a-user กำลังจัดการกับชื่อไฟล์ และได้รับfind
ข้อเสนอ-exec
อาร์กิวเมนต์ซึ่งช่วยให้คุณสร้างบรรทัดคำสั่งก็ไม่เป็นไร (ตราบใดที่mycommand
ได้รับอนุญาตให้ดำเนินการมากกว่าหนึ่งครั้งถ้าไม่ใช่เรามีปัญหาอีกอย่างกับการใช้xargs
ที่นี่ ... )
วิธีที่ดีกว่าในการจัดการกับมัน (IMO) คือ:
ในzsh
:
l=(a b c)
mycommand -f$^l
หรือใช้การซิปอาร์เรย์เพื่อให้อาร์กิวเมนต์ไม่ถูกแนบกับตัวเลือก:
l=(a b c) o=(-f)
mycommand "${o:^^l}"
ด้วยวิธีนี้จะยังคงทำงานได้หากl
อาร์เรย์มีองค์ประกอบว่างเปล่าหรือองค์ประกอบที่มีช่องว่างหรืออักขระที่มีปัญหาอื่น ๆxargs
ๆ ตัวอย่าง:
$ l=(a '' '"' 'x y' c) o=(-f)
$ printf '<%s>\n' "${o:^^l}"
<-f>
<a>
<-f>
<>
<-f>
<">
<-f>
<x y>
<-f>
<c>
ใน rc
:
l=(a b c)
mycommand -f$l
ใน fish
:
set l a b c
mycommand -f$l
(AFAIK rc
และfish
ไม่มีการซิปอาร์เรย์)
ด้วยเชลล์แบบเหมือน Bourne แบบเก่าbash
คุณสามารถทำได้ตลอดเวลา (ยังคงอนุญาตให้ตัวละครใด ๆ ในองค์ประกอบของ$@
อาร์เรย์):
set -- a b c
for i do set -- "$@" -f "$i"; shift; done
mycommand "$@"
for i; do args+=('-f' "$i");done;
mycommand "${args[@]}"
. IDK ถ้าสิ่งนี้เร็วกว่า แต่การผนวก 2 องค์ประกอบเข้ากับอาร์เรย์ดูเหมือนว่าควรเป็น O (n) ในขณะที่set
ลูปของคุณอาจคัดลอกและแยกวิเคราะห์รายการ ARG ที่สะสมใหม่ทุกครั้ง (O (n ^ 2))
ARG_MAX
และมีการ-f
แยกออกจากพารามิเตอร์ที่จับคู่