Sed

如何用’遞歸替換字元串?

  • July 16, 2022

在 macOS 下的 zsh 終端視窗中,我試圖在目前目錄中開始的所有文件(Y, d')\opair{Y, d'}遞歸地替換所有實例。.tex

以下似乎什麼都不做:

find . -type f -name "*.tex" -print0 | xargs -0 sed -i '.bak' -e "s/(Y, d')/\\opair{Y, d'}/g"

我該如何解決?

我確實嘗試過轉義'(根據sed我看到的文件,實際上並不需要轉義),但這並不能解決問題。

find . -name '*.tex' -type f -exec \
 sed -i.bak -e "s/(Y, d')/\\\\opair{Y, d'}/g" {} +
  • 你有X而不是Y
  • 不需要xargs, 當您可以使用標準-exec cmd {} +語法時。
  • \需要對 shell 進行轉義(在雙引號內仍然是特殊的)和sed. 或者,您可以做's/(Y, d'\'')/\\opair{Y, d'\''}/g'or inrc或 in zshafter set -o rcquotes's/(Y, d'')/\\opair{Y, d''}/g'\在單曲中並不特殊(儘管問題現在轉移到如何將's 傳遞給sed)。
  • for find,-name通常比測試更便宜,-type所以最好把它放在第一位(find儘管有些實現自己重新排序作為優化)。
  • 對於sedFreeBSD 以外的實現(這也是在 macos 上找到的實現),備份後綴必須附加到-i選項上。在 FreeBSD 和 macos 上,兩者都-i .bak可以-i.bak工作,但後者更便攜,更面向未來,因為 FreeBSD/macos 可能會選擇在未來與其他實現保持一致。

還要注意有很多看起來相同的字元和一些不可見的字元(包括一些控製字元)。例如,您確定 and 之間的空格Y,d'ASCII 空格 (U+0020) 而不是不間斷空格 (U+00A0)?或者那'是 ASCII 撇號而不是 U+2019,正確的引用?

vim中,ga為您提供有關游標下字元的資訊。uconv -x name < file為您提供輸入中每個字元的名稱。

reveal() {
 perl -Mcharnames=full -Mopen=locale -pe 's{[^\t\n -~]}{
   sprintf "<U+%04X %s>", ord($&), charnames::viacode(ord($&))}ge' "$@"
}

可用於顯示*(*例如)除空格、製表符、換行符和 ASCII 可列印字元以外的字元。<U+3000 IDEOGRAPHIC SPACE>St<U+00E9 LATIN SMALL LETTER E WITH ACUTE>phane``Stéphane

另請注意,對於某些find實現,包括 GNUfind系統上的 GNU,-name '*.tex'可能無法匹配以結尾.tex但其餘部分無法解碼為目前語言環境中的字元的文件名。例如,它會跳過$'St\xe9phane'在使用 UTF-8 作為其字元編碼的語言環境中呼叫的文件,因為單獨的 0xe9 字節不能被解碼為字元。為命令加上前綴LC_ALL=C可以解決這個問題。

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