PowerShell:在传递给外部程序的字符串中转义双引号的最佳方法是什么?例如,JSON字符串。

5

我阅读了所有关于在 PowerShell 中转义字符串的文章,但仍然没有找到能满足我的解决方案。

假设我有一个包含 JSON 字符串的文件 foo.json。 我需要将 JSON 字符串作为参数传递给一个程序。

在 bash 中,这很好用:

myprogram "$(cat ~/foo.json)"

在 PowerShell 中,当我正常读取文件内容并进行传递时,接收程序会抱怨键和值周围没有引号。

我想到的方法是:

$json = (get-content ~/foo.json | Out-String) -replace '"','""' myprogram $json

在 PowerShell 中有更简单的方法吗?我已经退回到退出会话,在 bash 中运行命令,然后再次启动会话。


1
在json文件中,所有的键和值都要加引号,除了数字值。如果你想将json文件作为字符串传递,并且该文件包含这些引号字符,那么当你使用myprogram (Get-Content foo.json -Raw)读取时,它们不会被改变。 - Theo
@Theo:这里的问题是PowerShell在将带有嵌入式"字符的字符串传递给_外部程序_时缺乏引号。 - mklement0
2个回答

14
很遗憾,PowerShell在将带有嵌入双引号的参数传递给外部程序时存在问题,直到PowerShell 7.2.x版本为止。这要求您手动进行转义,使用\"来表示双引号:
  • 有关底层问题的更多信息,请参阅this answer

一个强大的解决方法不仅需要将所有的"替换为\",还需要将其之前紧挨着的任何\都加倍。
# Note: If your JSON has no embedded *escaped* double quotes
#       - \" - you can get away with: -replace '"', '\"'
myprogram ((Get-Content -Raw ~/foo.json) -replace '(\\*)"', '$1$1\"')

注意使用Get-Content -Raw,与将整个文件读入一个单一的多行字符串的Get-Content ... | Out-String相比,这是更可取的,但请注意它需要PSv3+。


假设您的JSON中要么根本没有转义序列,要么只有\"的实例,那么一个更简单的解决方法是通过ConvertTo-Json将JSON字符串再次编码为JSON。这个方法是由Vivere发现的。
# Works, but only if your JSON contains no escape sequences
# such as \n or \\
myprogram (Get-Content -Raw ~/foo.json | ConvertTo-Json)

此外,是否有理由更喜欢使用单引号(')而不是双引号(")? - Tatiana Racheva
很高兴听到这个消息,@TatianaRacheva。 为保持一致性,您可能更喜欢使用\"作为转义字符,因为`是通用的转义字符,但在"..."内使用""也可以正常工作;请注意,在'...'内,只有使用''`才能嵌入单引号。 - mklement0

0
在我的情况下,在调用参数之前,我已经将所有的双引号替换为单引号,并且只在开头和结尾设置双引号。在 Powershell 脚本中非常有效。
在我的场景中,我是从 Groovy 中调用 Powershell。
changeorderParam 是我存储 Json 字符串的地方。
changeorderParam = changeorderParam.replaceAll("\"", "'")
bat "powershell.exe -Executionpolicy bypass -file C:\\\scripts\\\script.ps1 \\\"${template}\\\" \\"${script}\\" \\"${branch}\\" \\"${changeorderParam}\\""  

希望这能帮助到某人!


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