微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何编写正则表达式来匹配多行模式?

如何解决如何编写正则表达式来匹配多行模式?

我正在尝试使用 PowerShell 解析 SFTP 配置文件 (sshd_config.txt) 以获取所有现有的 SFTP 配置文件。下面的文本只是 3 个配置文件,但可能有数百个我需要解析。一旦我有一个有效的正则表达式将所有匹配项输出到 PowerShell 对象,我就可以解析各个配置文件了。我只是不知道如何编写正则表达式。我确实尝试使用其他示例,但我无法将每个示例分成单独的匹配项。

我需要匹配开始“^Match”和所有行直到一个空行。任何帮助将不胜感激。

Match User thedomain\user1
    ChrootDirectory E:\sftp\heatism\user1
    PermitTunnel no
    AllowAgentForwarding no
    AllowTcpForwarding no
    X11Forwarding no
    ForceCommand internal-sftp

Match User thedomain\user2
    ChrootDirectory E:\sftp\heatism\user2
    PermitTunnel no
    AllowAgentForwarding no
    AllowTcpForwarding no
    X11Forwarding no
    ForceCommand internal-sftp

Match User thedomain\user3
    ChrootDirectory E:\sftp\heatism\user3
    PermitTunnel no
    AllowAgentForwarding no
    AllowTcpForwarding no
    X11Forwarding no
    ForceCommand internal-sftp

解决方法

跨多行匹配:

  • 您需要一个单行多行字符串作为输入,这就是 Get-Content-Raw 开关提供的(默认情况下,Get-Content 输出输入文件的行 一一).

  • 此外,您的 regex 必须使用以下 options

    • Multiline (m),为了使^$匹配单行的开头和结尾多行字符串; \A\Z(或 \z,仅匹配字符串的末尾,即使它是换行符)然后可用于匹配多个的整体开头和结尾-line 字符串。

    • Singleline (s) 如果您希望 . 也匹配 换行符 字符 (\n)。

    • 指定这些选项的最简单方法是在正则表达式开头的 (?...) 内;在手头的情况下:(?ms)

总而言之,使用 Jan's helpful regex 的修改版本和 .NET System.Text.RegularExpressions.Regex.Matches() 方法来查找给定正则表达式的 all 匹配项(注意 PowerShell 的 {{ 3}} 只查找 first):

foreach ($m in [regex]::Matches(
  (Get-Content -Raw sshd_config.txt),'(?ms)^Match User .+?(?=^$|\Z)'
)) {
  # Split the block of line into the first and the remaining lines.  
  $first,$rest = $m.Value.Trim() -split '\r?\n'
  # Create an aux. (ordered) hashtable and fill it with the user name
  # extracted from the first line.
  $oht = [ordered] @{ UserName = (-split $first)[-1] }
  # Loop over the remaining lines,split them into name and value,# and add them to the hashtable.
  foreach ($line in $rest) {
    $name,$value = $line.Trim() -split ' ',2
    $oht[$name] = $value
  }
  # Convert the hashtable to a custom object and output it.
  [pscustomobject] $oht
}

通过您的示例输入,您将看到以下输出,代表所创建的 [pscustomobject] 实例的默认格式:

UserName             : thedomain\user1
ChrootDirectory      : E:\sftp\heatism\user1
PermitTunnel         : no
AllowAgentForwarding : no
AllowTcpForwarding   : no
X11Forwarding        : no
ForceCommand         : internal-sftp

UserName             : thedomain\user2
ChrootDirectory      : E:\sftp\heatism\user2
PermitTunnel         : no
AllowAgentForwarding : no
AllowTcpForwarding   : no
X11Forwarding        : no
ForceCommand         : internal-sftp

UserName             : thedomain\user3
ChrootDirectory      : E:\sftp\heatism\user3
PermitTunnel         : no
AllowAgentForwarding : no
AllowTcpForwarding   : no
X11Forwarding        : no
ForceCommand         : internal-sftp
,

您可以使用(感谢 @mklement0 的一些改进):

(?m)^Match[\s\S]+?(?=^$|\Z)

查看 a demo on regex101.com 并注意 multiline 标志。


说明:

^Match    # match "Match" at the very beginning of a line
[\s\S]*?  # match anything else lazily
(?=^$|\Z) # make sure what follows is a blank line or the very end of the string
,

另一种选择是以 Match 开始模式,然后是该行的其余部分。然后继续使用负前瞻匹配所有非空行。

^Match .*(?:\r?\n(?!$).*)*

模式匹配:

  • ^Match
  • .* 匹配该行的其余部分
  • (?: 非捕获组
    • \r?\n(?!$) 匹配换行符并断言该行不为空
    • .* 匹配该行的其余部分
  • )* 关闭非捕获组并可选择重复

看到一个 regex demo

如果您也不想匹配仅包含空格的行:

^Match .*(?:\r?\n(?![\p{Zs}\t]*$).*)*

示例

$allText = Get-Content -Raw sshd_config.txt
$pattern = "(?m)^Match .*(?:\r?\n(?![\p{Zs}\t]*$).*)*"
Select-String $pattern -input $allText -AllMatches | Foreach-Object {$_.Matches} | Foreach-Object {
    $_.Value 
    "--------------------------"
}

输出

Match User thedomain\user1
    ChrootDirectory E:\sftp\heatism\user1
    PermitTunnel no
    AllowAgentForwarding no
    AllowTcpForwarding no
    X11Forwarding no
    ForceCommand internal-sftp
--------------------------
Match User thedomain\user2
    ChrootDirectory E:\sftp\heatism\user2
    PermitTunnel no
    AllowAgentForwarding no
    AllowTcpForwarding no
    X11Forwarding no
    ForceCommand internal-sftp
--------------------------
Match User thedomain\user3
    ChrootDirectory E:\sftp\heatism\user3
    PermitTunnel no
    AllowAgentForwarding no
    AllowTcpForwarding no
    X11Forwarding no
    ForceCommand internal-sftp
--------------------------

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。