如何在PowerShell中的ACK命令中转义双引号和冒号

4

我正在使用PowerShell中的Ack版本2.04。我想在文本文件中搜索文本,例如"jsonClass":"Page"(包括引号)。

我似乎无法正确地进行引用和转义。

ack -c --match '"jsonClass":"Page"'

在PowerShell中它不起作用。我猜ack也会捕获单引号。

转义双引号会导致无效的正则表达式错误:

ack -c --match "\"jsonClass\":\"Page\""
  Invalid regex '\':
  Trailing \ in regex m/\/ at C:\CHOCOL~1\lib\ACK2~1.04\content\ack.pl line 315

我也尝试了字面量选项,但我认为ack将冒号解释为文件参数。

ack -c -Q --match "jsonClass":"Page"
  ack.pl: :Page: No such file or directory

我错过了什么?
我正在使用PowerShell v2。

什么是 ack 命令/cmdlet/function? - saftargholi
@arashzgh http://beyondgrep.com/ - sas1138
我正在使用 PowerShell 2.0。 - sas1138
3个回答

6
为了补充JPBlanc的有效答案,提供一个基于PowerShell v3+的解决方案:
调用外部程序(例如ack)时,使用所谓的停止解析符号--%,使得PowerShell将剩余的参数按原样传递,除了扩展类似%PATH%cmd.exe风格的环境变量引用之外。
ack --% -c --match "\"jsonClass\":\"Page\""

这样做可以让你只关注目标程序的转义规则,而不用担心与PowerShell自身解析和转义的复杂相互作用。因此,在PowerShell v3或更高版本中,原帖中的第二种解决方案尝试通过将--%作为第一个参数传递来实现也是可行的。请参阅Get-Help about_Parsing
请注意,上述命令的确切等效命令,不使用--%(也适用于PSv2并且通常很有帮助如果您想在其他参数中包含PowerShell扩展变量/表达式),如下所示:
ack -c --match '"\"jsonClass\":\"Page\""'

那就是说,要传递的整个参数被包含在单引号中,这可以确保PowerShell不解释它。请注意,内部有双引号,这在JPBlanc的回答中不存在(截至本文撰写时)。它们保证了即使包含空格,该参数最终也被视为单个参数由ack看到。

我正在使用PowerShell v2,并且上述的转义并不能解决问题,因为似乎传递给ack的参数也包含反引号。 - sas1138
@sas1138:我已经重写了答案。现在它只对PSv3+用户有用,但是由于您没有将帖子标记为仅限v2(请现在保持这种方式),因此我想展示一个可能对未来读者有用的PSv3+替代方法。(我的原始答案错误在于我试图修复您的_PowerShell解决方案尝试_而不是解决您的原始问题;请注意,反引号不会被传递给ack,因为反引号是PS的_escape char_。) - mklement0
谢谢,我尝试过编辑,但是我还没有足够的权限来编辑帖子。 - sas1138
@sas1138 你应该始终能够编辑自己的帖子(如果已登录)。 (只是为了更正我的先前评论:我现在也添加了一个PSv2解决方案。) - mklement0

4

如果 ack 是一个函数,那么 PowerShell 可能会解释 -c。你能测试一下以下内容吗?

ack '-c' '--match' '"jsonClass":"Page"'

-c --match 应该被理解为在函数 ask 中参数 c 的值是 --match

如果是一个EXE文件,请尝试:

ack -c --match '\"jsonClass\":\"Page\"'

这似乎不是问题的原因。 - sas1138
我尝试了在简单模式下使用没有引号的-c,它返回了预期的结果。ack -c -Q --match "Page" - sas1138
3
ack 是一个 Perl 脚本/模块。当字符串被 Perl 处理时,需要使用反斜杠。'\"jsonClass\":\"Page\"'"\`"jsonClass\`":\`"Page\`"" 都可以正常工作。 - Ansgar Wiechers
@ansgar-wiechers,是的,我也通过试验和错误找到了第一种模式。请将其发布为答案。 - sas1138
1
好的回答,但为了完全复制 raw 参数 "\"jsonClass\":\"Page\"", 我建议将单引号字符串的内容用双引号括起来:'"\"jsonClass\":\"Page\""'。这在手头的字符串中没有任何区别,因为它不包含空格,但在其他情况下可能会有所不同。补充一下 @AnsgarWiechers 的澄清:在 Windows 上,ack 是作为批处理文件 (ack.cmd) 实现的,它调用脚本 ack.pl 来执行 perl.exe - mklement0

1
在Powershell中,您总是可以使用'引号来处理内部的"而不会出现问题。
但是,如果您需要使用"来表示字符串(例如插入一个变量),您可以使用`进行转义。
$myvar = 'test'
$formatted = "{`"value`":`"$myvar`"}"

Write-Host $formatted
# output: {"value":"test"}

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