【问题标题】:Regex to match "here strings" in PowerShell code正则表达式匹配 PowerShell 代码中的“此处字符串”
【发布时间】:2021-11-02 11:46:03
【问题描述】:

我正在寻找一个正则表达式来匹配 PowerShell 中的字符串 @'...'@ 和 @"..."@ 是 here strings

规则:

  1. 开始后总是跟新行(@' 或@")
  2. end 后没有字符('@ 或 "@),它始终位于行首,但后面可以有更多文字
  3. 外部@' .. '@ 可能包含内部@" "@,但在这种情况下,外部将被匹配。

示例

  1. 将匹配外部(包括hello)的示例
$MyString = @"
hello
@'
'@
bye
"@
  1. 将匹配外部(包括hello)的其他示例
$MyString = @'
hello
@"
"@
bye
'@
  1. 来自 Microsoft 的示例
$page = [XML] @"
    <command:command xmlns:maml="http://schemas.microsoft.com/maml/2004/10"
    xmlns:command="http://schemas.microsoft.com/maml/dev/command/2004/10" 
    xmlns:dev="http://schemas.microsoft.com/maml/dev/2004/10">
    <command:details>
            <command:name>
                   Format-Table
            </command:name>
            <maml:description>
                <maml:para>Formats the output as a table.</maml:para>
            </maml:description>
            <command:verb>format</command:verb>
            <command:noun>table</command:noun>
            <dev:version></dev:version>
    </command:details>
    ...
    </command:command>
"@

如果有任何帮助,我将不胜感激。我正在尝试解决内联问题,以获得对privacy.sexy 的更好的 PowerShell 模板支持,这样您的帮助将扩大到社区中的更多范围。

【问题讨论】:

    标签: regex powershell


    【解决方案1】:

    您最好使用 PowerShell 的语言解析器,System.Management.Automation.Language.Parser,而不是基于正则表达式的解决方案。[1]

    我假设你总是对 outer here-string 感兴趣,而不是碰巧嵌套在另一个字符串中。

    假设文件file.ps1 具有以下逐字逐句的内容:

    $MyString1 = @'
    hello
    @"
    "@
    bye
    '@
    
    $MyString2 = @"
    hello
    @'
    '@
    bye
    "@
    

    以下命令:

    $ast = [System.Management.Automation.Language.Parser]::ParseInput(
      (Get-Content -Raw file.ps1), 
      [ref] $null,
      [ref] $null
    )
    
    $ast.FindAll(
      { 
        $args[0] -is [System.Management.Automation.Language.StringConstantExpressionAst] -and
          $args[0].StringConstantType -in 'SingleQuotedHereString', 'DoubleQuotedHereString' 
      },
      $true
    ) | Format-Table StringConstantType, Value -Wrap
    

    输出:

        StringConstantType Value
        ------------------ -----
    SingleQuotedHereString hello
                           @"
                           "@
                           bye
    DoubleQuotedHereString hello
                           @'
                           '@
                           bye
    

    [1] 基于正则表达式的解决方案可能会产生误报,这几乎是无法避免的。示例见MikeM's answer;另一个是这里的字符串,恰好通过&lt;# ... #&gt;

    注释掉

    【讨论】:

      【解决方案2】:

      一个正则表达式解决方案,例如,例如,

      "@(""|')\r?\n[\s\S]*?\r?\n\1@(?=\r?\n|$)"
      

      或

      "(?ms)@(""|')\r?$.*?^\1@(?=\r?$)"
      

      可能已经足够了,尽管可能会出现错误匹配。

      例如,以下有效的 Powershell 代码中没有实际的 here-string,但上面的正则表达式会产生匹配。

      $MyString = "Definitely @'
      not a
      '@
      here-string
      "
      

      【讨论】:

      • 另一个潜在的误报来源是此处通过&lt;# ... #&gt; 注释掉的字符串。最终,只有语言解析器才能稳健地工作。顺便说一句:在 PowerShell 中形成的一个好习惯是对正则表达式使用 single 引用的(逐字)字符串文字 ('...'),以避免混淆 PowerShell 的可扩展字符串 (@987654327) @) 预先插入与 .NET 正则表达式引擎最终看到的内容。
      • 我认为您的回答很棒@mklement0,并感谢您对所有有效点/示例的解释。我相信这些信息将为来到这里的许多人提供很好的解决方案和见解。但是我会用稳健性来换取自定义解析器,因为我的解析器是用另一种语言(JavaScript)编写的。并且简单(RegEx 而不是更复杂的逻辑)是首选。
      • 没有一个解决方案匹配任何东西:regex101.com/r/u1HVEP/1,但感谢您的想法。 \1 很棒!
      • @U.Bulle 对不起,我在结束语之前收到了第二个@。现在更正了。请注意,以上内容用于 Powershell,因此双引号用双引号转义。没有转义,我们有例如(?ms)@("|')\r?$.*?^\1@(?=\r?$)。 Regex101 example.
      猜你喜欢
      • 2015-03-05
      • 2013-08-02
      • 1970-01-01
      • 2014-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-05
      • 2013-12-25
      相关资源
      最近更新 更多