
該expand
命令沒有相當於
sed -i <file>
expand
實際上確實有一個-i
選擇 - 但這意味著
僅在空格之後
有沒有一種sed
動態expand
的二人組合可以達到同樣的目的?
答案1
GNU 實用程式 Expand 不提供 sed 所提供的「就地」更新。儘管命令可能稍長,但重現相同的結果相當簡單。
在沒有損壞風險的情況下不可能在任意文件系統上同時解析和更新文件,因此 sed 和其他 sed 實際上並沒有這樣做,儘管它從用戶那裡抽象化了它。 sed 的作用(您可以自己重現)是將物件檔案上的操作輸出保存在臨時檔案中,然後刪除原始副本並將臨時檔案重新命名為原始檔案。
有多種方法可以做到這一點,這裡是一種 - 名為 orig.txt 的檔案是正在「擴展」的檔案:
tmp=`mktemp` && expand orig.txt > "$tmp" && mv "$tmp" orig.txt
如果您從不使用檔案名稱之外的任何參數來擴展,則一個名為 的簡單函數expand
可以將整個臨時檔案隱藏到原始檔案交換中,並重現該sed
行為- 此實作將採用路徑/檔案名稱的單個參數
expand() {
[[ "$#" -ne "1" ]] && { echo "A single argument must be provided"; exit 1; }
tmp=`mktemp` && expand "$1" > "$tmp" && mv "$tmp" "$1"
}
透過一點修改,我們可以expand
透過支援參數來重新建立所有功能。取得最後一個參數有一個小技巧,以便我們知道目標檔案的檔案名,以便我們最終可以用expand
.最後一個參數被引用為${@ -1}
。
expand() {
[[ "$#" -lt "1" ]] && { echo "At least a file name argument must be provided"; exit 1; }
# Here we capture the last argument which is the object file name
fname="${@: -1}"
# The upcoming call to expand passes on all arguments including the file name
tmp=`mktemp` && expand "$@" > "$tmp" && mv "$tmp" "$fname"
}
我沒有測試這段程式碼,所以如果有我沒有發現的語法錯誤,我深表歉意。
應將這些函數之一或它們的一個版本放入.bashrc
建立新 shell 時取得的等效檔案中,以便隨時可用。
如果您希望能夠指定檔案是否「就地」更新或更新是否傳送到 stdout,可以根據附加參數修改此函數範本以執行此操作(該參數不會傳遞給擴展,但改變了我們所說的擴展)。我不確定您是否正在尋找這個,但我認為如果您正在尋找的話,您現在已經擁有了執行此操作所需的所有資訊。
或為了獲得更多樂趣,請下載 GNU coreutils原始碼和sed原始碼,請查看 sed 如何處理它,並將該程式碼遷移到新的改進版本的 Expand 中。將該變更發送回維護人員,您可能已經為所有未來的「擴展」用戶簡化了此操作。