Bash

如何在find ... -exec中轉義sed中的反斜杠?

  • November 4, 2017

我想更改不同子目錄中某些文件中的一行。這些文件將始終具有副檔名.dct,並且它們將始終位於mod工作目錄的另一個子目錄中呼叫的子目錄中(但是有很多mod子目錄,所以我使用find)。但我要更改的字元串是目錄(Windows -> Unix)。

我可以使用find . -type f -path '*/mod/*.dct. 我試過用sed -e 's/cd c:\\project\\data\\/cd \/project\/data\//' $(basename {}) > $(basename {}).mod.

我將其縮小到逃脫的反斜杠是罪魁禍首。這有效:

find . -type -f -path '*/mod/*.dct' -execdir sh -c "sed -e 's/c://' $(basename {}) > $(basename {}).mod"

這不會:

find . -type -f -path '*/mod/*.dct' -execdir sh -c "sed -e 's/c:\\//' $(basename {}) > $(basename {}).mod"

這是錯誤

sed: -e expression #1, char 7: unterminated `s' command

char 7部分讓我認為轉義存在一些問題。看起來是這樣,但我不知道如何解決它。為了說明,這有效:

find . -type -f -path '*/mod/*.dct' -execdir sh -c "sed -e 's/c:\\//' $(basename {}) > $(basename {}).mod"

所以它看起來像是sed -e 's/c:\\///'被轉義為“c:\/用任何東西替換”並且sed -e 's/c:\\//'被轉義為“c:\/用……替換”(這會引發錯誤)而不是“c:\用任何東西替換”。

注意:使用-execdirandbasename而不是-exec可能有點矯枉過正,但我在某處讀到它是一種很好的形式。

您問題的本質是如何通過呼叫from\用正斜杠(ie)替換反斜杠(ie)。為此,您必須對反斜杠進行雙重轉義,因為該字元串將被處理兩次:一次通過呼叫 ,然後第二次通過呼叫. 這應該為您提供以下資訊:/``sed``find``find``sed

find . -type f -path '*/mod/*.dct' -execdir sh -c "sed -e 's/cd c:\\\\project\\\\data\\\\/cd \/project\/data\//' $(basename {}) > $(basename {}).mod" \;

更詳細的解釋如下。


首先,讓我們為您的問題設置一個稍微簡單的範例:

# Create a target directory
mkdir -p /tmp/dir1/mod/dir2

# Create a text file containing a backslash
echo '\' > /tmp/dir1/mod/dir2/file.dct

現在讓我們嘗試使用findsed用正斜杠替換該反斜杠:

find /tmp/dir1 -type f -path '*/mod/*.dct' -execdir sh -c "sed -e 's/\\/\//' $(basename {})" \;

這會產生以下錯誤:

sed: -e expression #1, char 7: unterminated `s' command

那是因為sed正在執行的命令是這樣的:

sed -e 's/\/\//' ./file.dct

您可以通過直接執行此命令來驗證您是否收到相同的錯誤,例如:

sed -e 's/\/\//' /tmp/dir1/mod/dir2/file.dct

您還可以通過echofind命令中執行來檢查這一點,例如:

find /tmp/dir1 -type f -path '*/mod/*.dct' -execdir echo "sed -e 's/\\/\//' $(basename {})" \;

為了修復命令,我們對反斜杠進行雙重轉義:

find . -type f -path '*/mod/*.dct' -execdir sh -c "sed -e 's/\\\\/\//' $(basename {})" \;

這會產生所需的結果:

/

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