สมมติว่าฉันมีเอาต์พุตบางส่วนจากคำสั่ง (เช่นls -1):
a
b
c
d
e
...
ฉันต้องการที่จะใช้คำสั่ง (พูดecho) กับแต่ละคนในทางกลับกัน เช่น
echo a
echo b
echo c
echo d
echo e
...
เป็นวิธีที่ง่ายที่สุดในการทุบตีอะไร
สมมติว่าฉันมีเอาต์พุตบางส่วนจากคำสั่ง (เช่นls -1):
a
b
c
d
e
...
ฉันต้องการที่จะใช้คำสั่ง (พูดecho) กับแต่ละคนในทางกลับกัน เช่น
echo a
echo b
echo c
echo d
echo e
...
เป็นวิธีที่ง่ายที่สุดในการทุบตีอะไร
คำตอบ:
xargsมันอาจจะง่ายที่สุดในการใช้งาน ในกรณีของคุณ:
ls -1 | xargs -L1 echo
-Lมั่นใจธงการป้อนข้อมูลที่อ่านได้อย่างถูกต้อง จากหน้าคนของxargs:
-L number
Call utility for every number non-empty lines read.
A line ending with a space continues to the next non-empty line. [...]
lsอัตโนมัติ-1ในท่อ
ls | xargs -L2 echoและls -1 | xargs -L2 echoให้ผลลัพธ์ที่แตกต่างกันสองรายการ อดีตถูกทั้งหมดในบรรทัดเดียว
xargsสามารถเรียกใช้ไฟล์ที่ปฏิบัติการได้เท่านั้นซึ่งไม่ใช่ฟังก์ชั่นของเชลล์หรือคำสั่งในตัวของเชลล์ สำหรับอดีตทางออกที่ดีที่สุดน่าจะเป็นวิธีที่มีreadการวนซ้ำ
-L1มีไว้สำหรับ
คุณสามารถใช้การดำเนินการเสริมพื้นฐานในแต่ละบรรทัด:
ls -1 | while read line ; do echo $line ; done
หรือคุณสามารถไพพ์เอาท์พุทเป็น sed เพื่อการทำงานที่ซับซ้อนมากขึ้น:
ls -1 | sed 's/^\(.*\)$/echo \1/'
sh: cho: not found a sh: cho: not foundดูเหมือนว่าeจะเป็นการใช้คำสั่ง in เพื่อเป็นคำสั่ง sed หรืออะไรบางอย่าง
whileลูป cmd1 | while read line; do cmd2 $line; done. หรือwhile read line; do cmd2 $line; done < <(cmd1)สิ่งที่ไม่ได้สร้าง subshell นี่เป็นเวอร์ชันที่เรียบง่ายของsedคำสั่งของคุณ:sed 's/.*/echo &/'
"$line"วนรอบในขณะเพื่อหลีกเลี่ยงการแยกคำ
read -r lineเพื่อป้องกันการreadสับสนกับตัวละครที่หลบหนี ตัวอย่างเช่นecho '"a \"nested\" quote"' | while read line; do echo "$line"; doneให้"a "nested" quote"ซึ่งสูญเสียการหลบหนี ถ้าเราทำecho '"a \"nested\" quote"' | while read -r line; do echo "$line"; doneเราจะได้รับ"a \"nested\" quote"ตามที่คาดไว้ ดูwiki.bash-hackers.org/commands/builtin/read
คุณสามารถใช้สำหรับการวนรอบ :
สำหรับไฟล์ใน *; ทำ echo "$ file" เสร็จแล้ว
โปรดทราบว่าหากคำสั่งที่เป็นปัญหายอมรับหลายอาร์กิวเมนต์การใช้xargsนั้นเกือบจะมีประสิทธิภาพมากกว่าเสมอเพราะจะต้องวางยูทิลิตีที่มีปัญหาไว้หนึ่งครั้งแทนที่จะเป็นหลาย ๆ ครั้ง
printf '%s\0' * | xargs -0 ...- มิฉะนั้นก็ค่อนข้างไม่ปลอดภัยกับชื่อไฟล์ด้วยช่องว่าง, คำพูด, ฯลฯ
คุณสามารถใช้ Sed เพื่อทำได้โดยที่มันเป็น GNU sed
... | sed 's/match/command \0/e'
มันทำงานอย่างไร:
cat /logs/lfa/Modified.trace.log.20150904.pw | sed -r 's/^(.*)(\|006\|00032\|)(.*)$/echo "\1\2\3 - ID `shuf -i 999-14999 -n 1`"/e'
for s in `cmd`; do echo $s; done
หาก cmd มีเอาต์พุตขนาดใหญ่:
cmd | xargs -L1 echo
cmdมีช่องว่างในเอาต์พุตช่องแรกจะล้มเหลว
xargs ล้มเหลวด้วยเครื่องหมายแบ็กสแลชเครื่องหมายคำพูด มันต้องเป็นอะไรซักอย่าง
ls -1 |tr \\n \\0 |xargs -0 -iTHIS echo "THIS is a file."
ตัวเลือก xargs -0:
-0, --null Input items are terminated by a null character instead of by whitespace, and the quotes and backslash are not special (every character is taken literally). Disables the end of file string, which is treated like any other argument. Useful when input items might contain white space, quote marks, or backslashes. The GNU find -print0 option produces input suitable for this mode.
ls -1ยุติรายการด้วยอักขระขึ้นบรรทัดใหม่ดังนั้นtrแปลเป็นอักขระ null
วิธีนี้ช้ากว่าการวนซ้ำด้วยตนเองประมาณ 50 เท่า for ... (ดูคำตอบของMichael Aaron Safyan ) (3.55s เทียบกับ 0.066s) แต่สำหรับคำสั่งอินพุตอื่น ๆ เช่นค้นหาค้นหาอ่านจากไฟล์ ( tr \\n \\0 <file) หรือคล้ายกันคุณต้องทำงานกับxargsสิ่งนี้
ผลลัพธ์ที่ดีกว่าสำหรับฉัน:
ls -1 | xargs -L1 -d "\n" CMD
find . -mindepth 1 -maxdepth 1 -print0 | xargs -0 commandจะจัดการกรณีที่ผลลัพธ์ของls -1ไม่ชัดเจน ใช้-printf '%P\0'แทน-print0ถ้าคุณไม่ต้องการนำหน้า./ในแต่ละอัน
ฉันชอบที่จะใช้เพ่งพิศเพื่อใช้หลายคำสั่งในรายการเช่น
ls -l | gawk '{system("/path/to/cmd.sh "$1)}'
อย่างไรก็ตามการหลบหนีของตัวละครที่หลบหลีกได้จะมีขนเล็กน้อย
ls -1อาจจะเป็นตัวอย่างที่นี่lsแต่มันเป็นสิ่งสำคัญที่ต้องจำไว้ว่ามันไม่ดีที่จะแยกการส่งออกของ ดู: mywiki.wooledge.org/ParsingLs