Shell-Script

為 AIX 重寫使用 sed -i 的查找命令

  • April 20, 2016

我有一個腳本可以搜尋字元串並通過 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!$!\\!');

引用自:https://unix.stackexchange.com/questions/277835