Как экранировать строковые переменные при вызове ExpandString в PowerShell - PullRequest
0 голосов
/ 30 мая 2018

У меня есть скрипт PowerShell, чтобы взять файл JSON в качестве параметра и преобразовать его в объект.В строке JSON (как шаблон) могут быть некоторые переменные, которые должны быть заменены фактическими значениями во время выполнения.Например, $var_1, $var_x и $var_y в этой строке JSON:

{
    "key1": "My name is ${var_1}",
    "key2":
    {
        "key3": "Another variable ${var_x}",
        "key4": "${var_y}"
    }
}

Имена этих переменных неизвестны сценарию.Я использую ExpandString для выполнения этой работы:

[string]$jsonText = Get-Content $inputFile;

if ([string]::IsNullOrWhiteSpace($jsonText)) {
    throw "No content in $inputFile"
}
$temp = $ExecutionContext.InvokeCommand.ExpandString($jsonText);
$jsonObj = ConvertFrom-Json $temp;

Проблема в том, что когда переменная содержит двойная кавычка , то вызов ConvertFrom-Json завершится неудачно, поскольку кавычка не экранирована.Например, "My name is ${var_1}" может стать "My name is a "new" name".

Есть ли способ избежать этих строковых переменных при вызове ExpandString?

Ответы [ 2 ]

0 голосов
/ 30 мая 2018

Разрешено ли в этом формате?Если переменная заключена в кавычки "", это строка, и она не добавит метки к .json.Например:

$var_1 = "Json Sample"
$json_piece = @"
{
    "key1": "My name is $var_1",
    "key2":
    {
        "key3": "Another variable $var_2",
        "key4": "$var_3"
    }
}
"@

Выводится ( $ var_2 и $ var_3 не определены ):

{
    "key1": "My name is Json Sample",
    "key2":
    {
        "key3": "Another variable ",
        "key4": ""
    }
}

Если вы добавите " в файл json, напримерthis:

{
    "key1": "My name is "Json Sample"",
    "key2":
    {
        "key3": "Another variable ",
        "key4": ""
    }
}

Вы допустите ошибку: Исключена запятая .Это означает, что если переменная содержит "", сначала вы должны экранировать их, в противном случае файл .json является неожиданным.


PS Проверка Я проверил ее на FREEFORMATTER.COM .
Это мой код:

{
  "Key": "value is "value"",
  "key2": "other value"
}

И я получаю 2 ошибки:

  • Вход JSON НЕ действителен согласнок RFC 4627 (спецификация JSON).Неожиданный токен v в позиции 20.
  • Ввод JSON НЕ действителен в JavaScript, отсутствует} после списка свойств (в строке № 2), (в позиции № 24)
0 голосов
/ 30 мая 2018

Вы можете использовать следующую технику, используя возможность встраивания полных операторов в ваш шаблон через $(...) оператор подвыражения;поэтому следует также отметить, что обычно следует использовать этот метод только с теми шаблонными строками, которым вы доверяете , учитывая, что могут выполняться произвольные команды.

$var_1 = '"new" name'

$template = @'
{ "key1": "My name is $((Get-Variable var_1).Value -replace '"', '\"')" }
'@

$ExecutionContext.InvokeCommand.ExpandString($template)

Выше приведено:

{ "key1": "My name is \"new\" name" }

, что является действительным JSON.

Обратите внимание на использование Get-Variable для доступа к значению переменной ${var_1} косвенно , поэтомучто его встроенные " символов.может быть безопасно экранирован как \", как того требует JSON.


Поскольку вышеприведенное является немного громоздким для нескольких ссылок, вы можете определить вспомогательную функцию :

$var_1 = '"new" name'

# Aux. function that takes a variable name and returns its value with
# " chars. \-escaped.
function esc ($varName) { (Get-Variable $varName).Value -replace '"', '\"' }    

# Now you can reference the variables using $(esc <var-name):
$template = @'
{ "key1": "My name is $(esc var_1)" }
'@

$ExecutionContext.InvokeCommand.ExpandString($template)

Если вы не управляете строкой шаблона , потребуется дополнительная работа:

$var_1 = '"new" name'

# Aux. function that takes a variable name and returns its value with
# " chars. \-escaped.
function esc ($varName) { (Get-Variable $varName).Value -replace '"', '\"' }

# The original template with ${var}-style references.
$template = @'
{
  "key1": "My name is ${var_1}",
}
'@

# Modify the template to replace ${var} references with $(esc var).
$modifiedTemplate = $template -replace '\$\{(\w+)\}', '$$(esc $1)'

# Now expand the modified template.
$ExecutionContext.InvokeCommand.ExpandString($modifiedTemplate)

Обратите внимание, что преобразование шаблона предполагает: Советшляпу briantist для его ввода.

  • , что нет экранированных ссылок на переменные, которые будут рассматриваться как литералы вшаблон ввода (например, `${var}).

  • , что все ссылки на переменные имеют форму ${varName}, где предполагается, что varName состоит только из букв, цифр и подчеркиваний (соответствует одному или нескольким \w экземплярам).

Более надежное решение, охватывающее все крайние случаи, может потребовать использования API синтаксического анализа PowerShell , что, однако, требует значительно больших усилий.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...