如何在“find ... -exec”内转义“sed”中的反斜杠?

如何在“find ... -exec”内转义“sed”中的反斜杠?

我想更改不同子目录中某些文件的一行。这些文件将始终具有扩展名.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可能有点矫枉过正,但我​​在某处读到这是一种很好的形式。

答案1

您问题的本质是如何通过调用from 将反斜杠(即\)替换为正斜杠(即/)。为此,您必须对反斜杠进行双转义,因为该字符串将被处理两次:一次通过调用 进行处理,第二次通过调用 进行处理。这应该给你以下信息:sedfindfindsed

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

现在让我们尝试使用反斜杠find并将sed其替换为正斜杠:

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 {})" \;

这会产生所需的结果:

/

相关内容