我需要从一行 json-data 中提取数据,它位于两个变量之间(Powershell)

I need to extract Data from a single line of json-data which is inbetween two variables (Powershell)

我需要从一行 json 数据中提取数据,它位于两个变量 (Powershell) 之间

我的变量: 在数据前面: 设备地址”:[{“ID”: 数据后: ,"

我试过了,但由于我使用的所有特殊字符,应该有一些错误:

$devicepattern = {DeviceAddresses":[{"Id":{.*?},"}
#$deviceid = [regex]::match($changeduserdata, $devicepattern).Groups[1].Value
#$deviceid

如您所见,某些字符文字不能按原样用于正则表达式模式中,因为它们具有特殊含义 - 我们称这些为 元字符

为了匹配输入字符串中相应的字符文字,我们需要使用\ -

对其进行转义
  • 为了匹配文字 (,我们使用转义序列 \(
  • 对于文字 },我们使用 \},依此类推...

幸运的是,您不需要知道或记住哪些是元字符或可转义序列 - 我们可以使用 Regex.Escape() 来转义 所有 特殊字符给定模式字符串中的文字:

$prefix = [regex]::Escape('DeviceAddresses":[{"Id":')
$capture = '(.*?)'
$suffix = [regex]::Escape(',"')
$devicePattern = "${prefix}${capture}${suffix}"

您也不需要直接调用 [regex]::Match,只要标量 -match 成功,PowerShell 就会使用匹配组填充自动 $Matches 变量:

if($changeduserdata -match $devicePattern){
  $deviceid = $Matches[1]
} else {
  Write-Error 'DeviceID not found'
}

作为参考,以下 ASCII 文字需要在 .NET 的正则表达式语法中进行转义:

$ ( ) * + . ? [ \ ^ { |

此外,# (常规 space 字符)需要转义,许多其他白色 space 字符必须转换为各自的字符转义序列使模式可以安全地用于 IgnorePatternWhitespace option(这不适用于您当前的情况):

\u0009 => '\t'   # Tab
\u000A => '\n'   # Line Feed
\u000C => '\f'   # Form Feed
\u000D => '\r'   # Carriage Return

...所有这些 Regex.Escape() 都为您考虑到了:)

补充

通常,请注意,如果将 JSON 数据解析为 objects[=,则数据更易于使用 - 并且处理更稳健91=] 您可以访问其属性 - 请参阅 底部部分

至于你的正则表达式尝试

  • 注意:以下内容也适用于所有 PowerShell-native 正则表达式功能,例如 -match-replace-split operators, the switch statement, and the Select-String cmdlet。

  • Mathias 的回答使用 [regex]::Escape() 转义要使用的正则表达式模式的部分 由正则表达式引擎逐字

    • 如果事先不知道这些 逐字部分 - 例如,当通过变量或表达式,或作为参数传递。
  • 但是,在指定为字符串的 正则表达式模式中 literal 通常更容易 单独 \-转义 正则表达式元字符,即那些在其他情况下具有特殊含义的字符正则表达式引擎。

    • 需要转义的字符列表是(可以从.NET Regular-Expression Quick Reference推断):
      • \ ( ) | . * + ? ^ $ [ {
      • 如果你启用IgnorePatternWhiteSpace option(你可以内联
        (?x),在模式的开头),你还必须 \-转义:
        • #
        • significant 空白字符(您实际想要匹配的字符)指定 verbatim(例如,' ',或通过字符串插值,"`t");这适用于通过转义序列指定的那些(例如,\t\n)。

因此,解决方案可以简化为:

# Sample JSON
$changeduserdata = '{"DeviceAddresses":[{"Id": 42,"More": "stuff"}]}'

# Note how [ and { are \-escaped
$deviceId = if ($changeduserdata -match 'DeviceAddresses":\[\{"Id":(.*?),"') {
  $Matches[1]
}

使用ConvertFrom-Json将JSON正确解析为对象既更健壮又更方便,因为它允许属性访问(点表示法)提取感兴趣的值:

# Sample JSON
$changeduserdata = '{"DeviceAddresses":[{"Id": 42,"More": "stuff"}]}'

# Convert to an object ([pscustomobject]) and drill down to the property
# of interest; note that the value of .DeviceAddresses is an *array* ([...]).
$deviceId = (ConvertFrom-Json $changeduserdata).DeviceAddresses[0].Id  # -> 42