หนึ่งสามารถแก้ปัญหาด้วยวิธีต่อไปนี้:
cat file | some_sed_command | tee file >/dev/null
ไม่
โอกาสที่file
จะถูกตัดลดลง แต่ไม่มีการรับประกันจะไม่ตัดcat file | some_sed_command | tee file >/dev/null
file
ทั้งหมดขึ้นอยู่กับคำสั่งที่มีการประมวลผลครั้งแรกขณะที่เมื่อเทียบกับสิ่งที่ใครบางคนอาจคาดหวังคำสั่งในท่อจะไม่ประมวลผลจากซ้ายไปขวา ไม่มีการรับประกันเกี่ยวกับคำสั่งที่จะเลือกก่อนดังนั้นหนึ่งอาจคิดว่ามันเป็นแบบสุ่มเลือกและไม่พึ่งพาเชลล์ไม่เลือกคำสั่งที่ผิด
เนื่องจากโอกาสในการกระทำผิดคำสั่งที่จะหยิบครั้งแรกในระหว่างสามคำสั่งจะต่ำกว่าโอกาสสำหรับคำสั่งที่กระทำผิดจะหยิบครั้งแรกในระหว่างสองคำสั่งก็มีโอกาสน้อยที่file
จะถูกตัด แต่ก็ยังคงที่จะเกิดขึ้น
script.sh
:
#!/bin/bash
for ((i=0; i<100; i++)); do
cat >file <<-EOF
foo
bar
EOF
cat file |
sed 's/bar/baz/' |
tee file >/dev/null
[ -s file ] &&
echo 'Not truncated' ||
echo 'Truncated'
done |
sort |
uniq -c
rm file
% bash script.sh
93 Not truncated
7 Truncated
% bash script.sh
98 Not truncated
2 Truncated
% bash script.sh
100 Not truncated
ดังนั้นไม่เคยcat file | some_sed_command | tee file >/dev/null
ใช้สิ่งที่ต้องการ ใช้sponge
ตามที่แนะนำ Oli
อีกทางเลือกหนึ่งสำหรับสภาพแวดล้อมที่ลึกกว่าและ / หรือไฟล์ที่ค่อนข้างเล็กเราอาจใช้สตริงที่นี่และการแทนที่คำสั่งเพื่ออ่านไฟล์ก่อนที่จะรันคำสั่งใด ๆ :
$ cat file
foo
bar
$ for ((i=0; i<100; i++)); do <<<"$(<file)" sed 's/bar/baz/' >file; done
$ cat file
foo
baz