我需要从两个变量(Powershell(之间的一行json数据中提取数据
我的变量:在Data前面:DeviceAddresses":[{"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'
}
为了参考,需要在.NET的正则表达式语法中转义以下ASCII文本:
$ ( ) * + . ? [ ^ { |
此外,#
和(常规空格字符(需要转义,并且许多其他空白字符必须转换为它们各自的转义序列,以使模式可以安全地与
IgnorePatternWhitespace
选项一起使用(这不适用于您当前的场景(:
u0009 => 't' # Tab
u000A => 'n' # Line Feed
u000C => 'f' # Form Feed
u000D => 'r' # Carriage Return
Regex.Escape()
为您考虑的所有因素:(
补充Mathias R.Jessen的有用答案:
一般来说,请注意,如果将JSON数据解析为可以访问其属性的对象,则该数据更容易处理,处理也更稳健-请参阅底部的部分。
至于您的正则表达式尝试:
-
注意:以下内容也适用于所有PowerShell本机正则表达式功能,如
-match
、-replace
和-split
运算符、switch
语句和Select-String
cmdlet。 -
Mathias的答案使用
[regex]::Escape()
来转义正则表达式引擎将逐字使用的正则表达式模式部分。- 如果这些逐字部分事先不知道,例如,通过变量或表达式提供,或作为参数传递时,这无疑是的最佳方法
-
但是,在指定为字符串literal的正则表达式模式中,通常更容易单独
-转义正则表达式元字符,即那些对正则表达式引擎具有特殊意义的字符。
- 需要转义的字符列表为(可以从.NET正则表达式快速参考中推断出(:
( ) | . * + ? ^ $ [ {
- 如果启用了
IgnorePatternWhiteSpace
选项(可以在模式开始时与(?x)
内联(,则还必须执行-escape:
#
- 逐字指定的重要空白字符(您实际想要匹配的字符((例如,
' '
,或通过字符串插值,"`t"
(;这不适用于通过转义序列指定的那些(例如t
或n
(
- 需要转义的字符列表为(可以从.NET正则表达式快速参考中推断出(:
因此,该解决方案可以简化为:
# 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