Người ta có thể giải quyết vấn đề theo cách sau:
cat file | some_sed_command | tee file >/dev/null
Không .
Cơ hội file
sẽ bị cắt giảm, nhưng không có gì đảm bảo cat file | some_sed_command | tee file >/dev/null
sẽ không bị cắt ngắn file
.
Tất cả phụ thuộc vào lệnh nào được xử lý trước, trái ngược với những gì người ta có thể mong đợi, các lệnh trong một đường ống không được xử lý từ trái sang phải . Không có gì đảm bảo về lệnh nào sẽ được chọn trước, vì vậy người ta cũng có thể nghĩ rằng nó được chọn ngẫu nhiên và không bao giờ dựa vào vỏ không chọn lệnh vi phạm.
Vì cơ hội để lệnh vi phạm được chọn trước ở giữa ba lệnh thấp hơn cơ hội để lệnh vi phạm được chọn trước ở giữa hai lệnh, nên ít có khả năng nó file
sẽ bị cắt ngắn, nhưng nó vẫn sẽ xảy ra .
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
Vì vậy, không bao giờ sử dụng một cái gì đó như cat file | some_sed_command | tee file >/dev/null
. Sử dụng sponge
như Oli đề nghị.
Để thay thế, đối với môi trường mạnh hơn và / hoặc các tệp tương đối nhỏ, người ta có thể sử dụng chuỗi ở đây và thay thế lệnh để đọc tệp trước khi chạy bất kỳ lệnh nào:
$ cat file
foo
bar
$ for ((i=0; i<100; i++)); do <<<"$(<file)" sed 's/bar/baz/' >file; done
$ cat file
foo
baz