【问题标题】:How to correctly build RegEx for multiline values in reg file如何为 reg 文件中的多行值正确构建 RegEx
【发布时间】:2019-01-15 18:18:02
【问题描述】:

我想从 .reg 文件(REG EXPORT 文件)中获取值,以便将它们与另一个 .reg 文件进行比较。我在为此创建 RegEx 时遇到问题。

让我更难的事实:

  1. 我不知道文件中使用了哪种注册表项类型(这就是为什么我要为所有不同类型(如字符串、dword、qword、多字符串...)构建一个正则表达式
  2. 不知道文件最后一个字符是不是换行符
  3. 我只想返回实际值,例如fa,ad,df,fa,ad,df,fa,ad 如果 regkey 是 "qword"=hex(b):fa,ad,df,fa,ad,df,fa,ad
$Text = @'
[HKEY_LOCAL_MACHINE\SOFTWARE\Test]
"String"="asfasdfasasfasdfasasfasdfasasfas"
"Binary"=hex:d3,45,34,53,45,34,53,45,34,53,45,34,53,45,34,53,45,34,5b,09,89,08,\
34,09,8a,ef,02,30,40,9a,ad,fa,d0
"DWORD"=dword:fefefefe
"multistring"=hex(7):61,00,62,00,6c,00,61,00,73,00,66,00,62,00,00,00,62,00,61,\
  00,6c,00,73,00,66,00,62,00,61,00,73,00,64,00,66,00,00,00,62,00,61,00,6c,00,\
  73,00,64,00,66,00,61,00,64,00,6c,00,66,00,00,00,61,00,73,00,64,00,66,00,61,\
  00,73,00,64,00,66,00,00,00,61,00,73,00,64,00,66,00,00,00,61,00,73,00,64,00,\
  00,00,66,00,61,00,73,00,64,00,00,00,66,00,61,00,73,00,64,00,66,00,61,00,73,\
  00,66,00,61,00,73,00,64,00,66,00,00,00,61,00,73,00,64,00,66,00,61,00,73,00,\
  64,00,66,00,61,00,73,00,64,00,00,00,61,00,73,00,64,00,66,00,61,00,73,00,64,\
  00,66,00,00,00,00,00
"qword"=hex(b):fa,ad,df,fa,ad,df,fa,ad
'@

# this one works
$key = "multistring"
$regex = ('(?ms)\"{0}\"=hex\(7\):(.+)\n' -f [RegEx]::Escape($key))
[regex]::Matches($Text, $regex) | foreach { $_.Groups[1].Value }

# this one does not work because there is no newline after the last line...
$key2 = "qword"
$regex2 = ('(?ms)\"{0}\"=hex\(b\):(.+)\n' -f [RegEx]::Escape($key2))
[regex]::Matches($Text, $regex2) | foreach { $_.Groups[1].Value } 

【问题讨论】:

  • 您可以将尾随换行设为可选\n? 或尝试(\n|$)
  • 您可以轻松地在数据末尾添加换行符。
  • 如果我尝试使用 @marekful 的示例使换行符成为可选,则返回的值始终包含直到文件末尾的所有字符,这意味着也会返回所有后续键(如果不是文件中的最后一个注册表项)

标签: regex powershell registry


【解决方案1】:

在您的正则表达式中,您使用(?s),这是一个modifier,它将使点匹配任何字符,包括换行符。所以.+ 将匹配到所有行的末尾。

您可以使用capturing group 来捕获冒号后面的部分。 首先使用\"{0}\"=hex\(7\):匹配冒号之前的部分

然后匹配后面的内容直到行尾,并使用负前瞻来检查后面的行是否不是以双引号之间的单词开头的行,后跟一个等号,如“qword”=。只要是这种情况,就匹配整个字符串。

您的代码可能如下所示:

$regex = \"{0}\"=hex\(7\):(.*(?:(?!\n"[^\n"]+"=)\n.*)*)

第二部分解释:

  • ( 捕获组将保持您的价值
    • .* 匹配除换行符以外的任何字符 0+ 次
    • (?:非捕获组
      • (?! 否定前瞻断言以下内容不是
        • \n"[^\n"]+"= 匹配 \n",否定 character class 以不匹配 \n" 中的任何一个
      • )\n.* 关闭负前瞻并匹配 \n 后跟除换行符以外的任何字符 0+ 次
    • )*关闭非捕获组并重复0+次
  • )关闭捕获组

示例模式

\"multistring\"=hex\(7\):(.*(?:(?!\n"[^\n"]+"=)\n.*)*)

Regex demo

【讨论】:

    【解决方案2】:

    .+ 是一个贪心表达式,修饰符(?s) 使. 匹配所有 个字符(包括换行符),因此(.+)\n 将匹配到最后一个换行符的所有内容。

    试试这样的:

    $regex = '"{0}"=hex\(b\):(.+(?:\n  .+)*)'
    

    这里你既不需要(?m) 也不需要(?s),因为你不希望. 包含换行符,并且你不希望匹配多行字符串中行的开头或结尾。 .+(?:\n .+)* 匹配前缀 hex(b): 之后的行的其余部分以及以两个连续空格开头的所有后续行。 (?:...) 只是一个非捕获组,因为不需要捕获单独组中的每一行。

    【讨论】:

    • 也非常感谢您,您的解决方案也很完美! :)
    猜你喜欢
    • 2013-03-17
    • 1970-01-01
    • 2012-08-09
    • 2015-09-07
    • 1970-01-01
    • 2012-02-03
    • 2021-05-06
    • 1970-01-01
    • 2022-01-26
    相关资源
    最近更新 更多