สมมติว่าฉันมีเอาต์พุตบางส่วนจากคำสั่ง (เช่น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