Shell
如何使用 sed -i(就地編輯)實現可移植性?
我正在為我的伺服器編寫 shell 腳本,這是一個執行 FreeBSD 的共享主機。我還希望能夠在執行 Linux 的 PC 上本地測試它們。因此,我試圖以可移植的方式編寫它們,但
sed
我認為沒有辦法做到這一點。我的網站的一部分使用生成的靜態 HTML 文件,並且此 sed 行在每次重新生成後插入正確的 DOCTYPE:
sed -i '1s/^/<!DOCTYPE html> \n/' ${file_name.html}
它適用
sed
於 Linux 上的 GNU,但 FreeBSDsed
期望-i
選項後的第一個參數是備份副本的擴展。這就是它的樣子:sed -i '' '1s/^/<!DOCTYPE html> \n/' ${file_name.html}
然而,GNU
sed
反過來又期望表達式緊跟在-i
. (它還需要使用換行符處理進行修復,但這已經在這裡回答了)當然,我可以在腳本的伺服器副本中包含此更改,但這會弄亂即我使用 VCS 進行版本控制。有沒有辦法通過 sed 以完全可移植的方式實現這一目標?
GNU sed 在
-i
. 副檔名必須在同一個參數中,中間沒有空格。此語法也適用於 BSD sed。sed -i.bak -e '…' SOMEFILE
請注意,在 BSD 上,
-i
當有多個輸入文件時也會改變行為:它們是獨立處理的(例如$
匹配每個文件的最後一行)。這也不適用於 BusyBox。如果您不想使用備份文件,可以檢查可用的 sed 版本。
case $(sed --help 2>&1) in *GNU*) set sed -i;; *) set sed -i '';; esac "$@" -e '…' "$file"
或者,為了避免破壞位置參數,定義一個函式。
case $(sed --help 2>&1) in *GNU*) sed_i () { sed -i "$@"; };; *) sed_i () { sed -i '' "$@"; };; esac sed_i -e '…' "$file"
如果您不想打擾,請使用 Perl。
perl -i -pe '…' "$file"
如果你想寫一個可移植的腳本,不要使用
-i
——它不在 POSIX 中。手動執行 sed 在後台所做的工作——它只是多了一行程式碼。sed -e '…' "$file" >"$file.new" mv -- "$file.new" "$file"