Nếu bạn muốn tương đương sed -i.bak
, nó khá đơn giản.
Xem xét tập lệnh này cho GNU sed:
#!/bin/sh
# Create an input file to demonstrate
trap 'rm -r "$dir"' EXIT
dir=$(mktemp -d)
grep -v '[[:upper:][:punct:]]' /usr/share/dict/words | head >"$dir/foo"
# sed program - removes 'aardvark' and 'aardvarks'
script='/aard/d'
##########
# What we want to do
sed -i.bak -e "$script" "$dir"
##########
# Prove that it worked
ls "$dir"
cat "$dir/foo"
Chúng ta chỉ cần thay thế dòng được đánh dấu bằng
cp "$dir/foo" "$dir/foo.bak" && sed -e "$script" "$dir/foo.bak" >"$dir/foo"
Thao tác này sẽ chuyển tệp hiện có thành bản sao lưu và ghi tệp mới.
Nếu chúng ta muốn tương đương với
sed -i -e "$script" "$dir" # no backup
sau đó nó phức tạp hơn một chút. Chúng ta có thể mở tệp để đọc dưới dạng đầu vào tiêu chuẩn, sau đó hủy liên kết tệp đó, trước khi chỉ đạo đầu ra của sed để thay thế nó:
( cp "$dir/foo" "$dir/foo.bak"; exec <"$dir/foo.bak"; rm "$dir/foo.bak"; exec sed -e "$script" >"$dir/foo" )
Chúng tôi làm điều này trong một vỏ phụ, để stdin ban đầu của chúng tôi vẫn có sẵn sau này. Có thể chuyển đổi đầu vào và chuyển trở lại mà không cần một mạng con, nhưng cách này có vẻ rõ ràng hơn đối với tôi.
Lưu ý rằng chúng tôi cẩn thận sao chép trước, thay vì tạo foo
tệp mới - điều này rất quan trọng nếu tệp được biết đến bởi nhiều tên (nghĩa là có liên kết cứng) và bạn muốn chắc chắn rằng mình không phá vỡ liên kết .
/usr/gnu/bin/sed
để nhận hỗ trợ -i.