如何在Windows/DOS下使用GNU grep转义双引号?

7
我正在尝试搜索所有文件中的Assembly="Foobar,并将输出定向到tmp.txt。
我已经尝试了以下命令(cmd/error):
grep -r "Assembly=\"Foobar" . >> tmp.txt 错误(参数无效)
grep -r "Assembly=""Foobar" . >> tmp.txt 错误(空间不足)
grep -r 'Assembly="Foobar' . >> tmp.txt 错误(空间不足)
非常令人沮丧。有什么建议吗?

1
没有,我见过/尝试过那个。 - WhiskerBiscuit
1个回答

15

你需要同时考虑到对于grep和cmd.exe需要转义引号。

grep希望引号被转义为\"

cmd.exe会将引号转义为^"。引号是一个状态机,意味着未转义的引号在引号语义上切换开和关。当引号被打开时,特殊字符如<, |, &等会被当作字面值处理。第一个未转义的引号开启引号语义,下一个引号关闭引号语义。只有在引号关闭时才能转义引号。不平衡的引号将导致其余部分被引用。所以在你的情况下,>>tmp.txt不会被cmd.exe视为重定向,因此它会作为参数传递给grep。

以下任何一种方法都可以:

grep -r "Assembly=\"Foobar^" . >>tmp.txt
grep -r ^"Assembly=\"Foobar" . >>tmp.txt
grep -r ^"Assembly=\^"Foobar^" . >>tmp.txt
grep -r Assembly=\^"Foobar . >>tmp.txt
如果您的搜索词包含空格,则grep需要引号,因此您需要使用前三种形式中的任意一种。最后一种形式在搜索词中包含空格时无法工作。

这个有效... grep -r ^"Assembly="Foobar" . >> c:\temp\tmp.txt - WhiskerBiscuit
不确定您所说的“引用是状态机”的意思。 - WhiskerBiscuit
@WhiskerBiscuit - 我更新了答案,试图改进状态机的描述。 - dbenham
@dbenham,我不理解前两个例子。在第一种情况下,我看到的是:"Assembly=\"Foobar^" ====> (SEM_ON)Assembly=\(SEM_OFF)Foobar^" ===> Assembly=\Foobar",这似乎不是OP所期望的结果。另外,在第二个例子中,^"Assembly=\"Foobar" ====> ^"Assembly=\(SEM_ON)Foobar(SEM_OFF) ====> "Assembly=\Foobar。我一定是漏掉了什么。你能告诉我错在哪里吗? - Julio
1
@Julio - cmd.exe在打开或关闭引号语义时不会删除引号 - 引号将传递给grep。唯一被cmd.exe删除的是^字符(前提是引号已关闭,因此它可以作为转义符)。 - dbenham
非常感谢 @dbenham!现在我完全明白了。 - Julio

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接