為 AIX 重寫使用 sed -i 的查找命令
我有一個腳本可以搜尋字元串並通過 sed 命令替換它。如果該字元串包含特殊字元,則腳本將對它們進行轉義(斜線除外,因為它是我目前的 sed 分隔符和列,因為它在 bash 行上標記了字元串)。
它是這樣的:
raw_searchstring='SearchForThis'; raw_replacementstring='ReplaceWithThis'; #Escape special characters: quoted_searchstring=$(printf %s "$raw_searchstring" | sed 's/[][()\.^$?*+]/\\&/g'); quoted_replacementstring=$(printf %s "$raw_replacementstring" | sed 's/[][()\.^$?*+]/\\&/g'); find ./ -type f -exec sed -i -r "s/$quoted_searchstring/$quoted_replacementstring/" {} \;
我在 Ubuntu 上對此進行了測試,效果很好。
但是,我需要在 AIX 系統上執行該腳本。由於它不支持使用 sed -i 進行內聯編輯,因此我嘗試了以下操作,正如此處類似問題所建議的那樣(AIX 的 sed - 就地編輯):
find ./ -type f -exec sed -r 's/$quoted_searchstring/$quoted_replacementstring/' infile > tmp.$$ && mv tmp.$$ infile {} \;
這是我得到錯誤的地方
find: missing argument to `-exec'
所以我試圖通過這一行傳遞多個 -exec 語句
find
:find /home/tobias/Desktop -type f -exec sed -r 's/$quoted_searchstring/$quoted_replacementstring/' infile > tmp.$$ {} \; -exec mv tmp.$$ infile {} \;
這也不起作用:
sed: can't read infile: No such file or directory
我不確定我做錯了什麼。你能幫我修復這行程式碼或指出正確的方向嗎?
您的嘗試不起作用,因為您嘗試在由 執行的命令中使用 shell 運算符,例如
&&
and ,但是您直接在命令中鍵入這些運算符,因此它們由呼叫 的 shell 執行。您的命令被解析為>``find``find
find … > tmp.$$ && mv …
例如,第一次
find
呼叫是find ./ -type f -exec sed 's/$quoted_searchstring/$quoted_replacementstring/' infile
輸出重定向到
tmp.$$
. 該命令還有其他問題:infile
應該是{}
(它是find
找到的文件),並且 sed 表達式周圍的單引號應該是雙引號,因為您在那裡使用了 shell 變數。由於您需要在由 執行的命令中使用 shell 結構,因此請
find
告訴find
執行 shell。find … -exec sh -c '…' {} \;
為避免引用困難,請將需要引用的內容(例如 sed 表達式)作為參數傳遞給
sh
.find ./ -type f -exec sh -c ' sed "$0" "$1" >"$1.new" && mv "$1.new" "$1" ' "s/$quoted_searchstring/$quoted_replacementstring/" {} \;
為了在輕微的易讀性損失下獲得輕微的性能提升,您可以使用
-exec … {} +
表單和 shell 循環。find ./ -type f -exec sh -c ' for x; do sed "$0" "$x" >"$x.new" && mv "$x.new" "$x"; done ' "s/$quoted_searchstring/$quoted_replacementstring/" {} +
或者,如果
ksh93
您的 AIX 上的版本不是太舊,您可以使用它的遞歸通配特性(在 ksh93p 中引入)。set -G for x in **; do [[ -f $x ]] || continue sed "s/$quoted_searchstring/$quoted_replacementstring/" "$x" >"$x.new" && mv "$x.new" "$x"; done
在任何情況下,請注意,您還需要調整字元串到正則表達式的轉換以生成基本的正則表達式,因為
-r
使用 ERE 的標誌是 GNU 擴展。您現有的程式碼也有一些錯誤:您忘記引用斜杠,並且您沒有在替換文本中引用正確的字元。quoted_searchstring=$(printf %s "$raw_searchstring" | sed 's![[\/.^$*]!\\&!g'); quoted_replacementstring=$(printf %s "$raw_replacementstring" | sed -e 's![][\/&]!\\&!g' -e '!$ s!$!\\!');