RegEx匹配Powershell中两个字符串之间的字符串

时间:2018-11-15 21:51:43

标签: regex powershell

这是我的示例数据:

  

选项failonnomatch on
  批量选项
  选项确认关闭
  打开sftp:// username:password@host.name.net:22 hostkey =“ ssh-rsa 1024   00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00“

     

获取File * .txt \ local \ path \ Client \ File.txt
  mv File * .txt / remote / archive /

     

关闭
  退出

我想创建一个powershell脚本来从该文本文件中提取信息。

我需要的物品清单:

  • 用户名
  • 密码
  • 主机
  • 端口
  • ssh键
  • 文件名
  • 本地路径
  • 远程路径

我希望,如果我学习了其中的一些方法,则该方法将适用于所有项目。我尝试使用以下powershell / regex提取ssh密钥:

$doc -match '(?<=hostkey=")(.*)(?=")' 

$ doc是示例数据

,但似乎返回整行。任何帮助将不胜感激。谢谢。

2 个答案:

答案 0 :(得分:1)

此方法使用标记设置为singleline, multiline, case insensitive的命名匹配项,然后使用$Matches.MatchName将项放入自定义对象中。

# fake reading in a text file as one string
#    in real life, use Get-Content -Raw
$InStuff = @'
open sftp://username:password@host.name.net:22 hostkey="ssh-rsa 1024 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00"

get File*.txt \SERVER\Path\Client\File.txt
'@

$Null = $InStuff -match '(?smi).+//(?<UserName>.+):(?<Password>.+)@(?<HostName>.+):(?<Port>.+) hostkey="(?<SshKey>.+)".+get .+ (?<FullFileName>\\.+)$'

[PSCustomObject]@{
    UserName = $Matches.UserName
    Password = $Matches.Password
    Port = $Matches.Port
    SshKey = $Matches.SshKey
    PathName = Split-Path -Path $Matches.FullFileName -Parent
    FileName = Split-Path -Path $Matches.FullFileName -Leaf
    }

输出...

UserName : username
Password : password
Port     : 22
SshKey   : ssh-rsa 1024 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00
PathName : \SERVER\Path\Client
FileName : File.txt

答案 1 :(得分:0)

如果-match返回一条整行 ,则表示您的-match操作的LHS是 array ,这反过来建议您使用Get-Content 而没有-Raw ,这会产生输入为 array 在这种情况下,-match充当过滤器

相反,请使用Get-Content -Raw将文件读取为单行多行字符串; 使用标量 LHS,
-match然后返回[bool]
,并在中报告匹配操作的结果自动变量$Matches (一个哈希表,其0条目包含整体匹配项,1第一个捕获组匹配的项,...):

# Read file as a whole, into a single, multi-line string.
$doc = Get-Content -Raw file.txt 

if ($doc -match '(?<=hostkey=")(.*)(?=")') {
   # Output what the 1st capture group captured
   $Matches[1]
}

使用您的样本输入,以上结果将产生
ssh-rsa 1024 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00


然后您可以扩展捕获多个令牌的方法,在这种情况下,我建议使用命名捕获组(?<name>...));以下示例使用这样的命名捕获组来提取多个感兴趣的令牌:

if ($doc -match '(?<=sftp://)(?<username>[^:]+):(?<password>[^@]+)@(?<host>[^:]+)'){
  # Output the named capture-group values.
  # Note that index notation (['username']) and property
  # notation (.username) can be used interchangeably.
  $Matches.username
  $Matches.password
  $Matches.host
}

使用您的示例输入,以上结果将产生:

username
password
host.name.net

您可以将以上内容扩展为捕获所有所有标记。
请注意,默认情况下.\n(换行符)不匹配。


可选阅读:使用xIgnoreWhiteSpace)选项使正则表达式更具可读性:

提取许多令牌可能会导致难以阅读的复杂正则表达式,在这种情况下,xIgnoreWhiteSpace)正则表达式选项可以提供帮助(作为内联选项{{1} }的开头):

(?x)

请注意,在匹配时如何忽略用于使正则表达式更具可读性(跨多行分布)的空白,而在输入中要匹配的空白必须转义(例如,匹配单个空格,if ($doc -match '(?x) (?<=sftp://)(?<username>[^:]+) :(?<password>[^@]+) @(?<host>[^:]+) :(?<port>\d+) \s+hostkey="(?<sshkey>.+?)" \n+get\ File\*\.txt\ (?<localpath>.+) \nmv\ File\*\.txt\ (?<remotepath>.+) '){ # Output the named capture-group values. $Matches.GetEnumerator() | ? Key -ne 0 } [ ]匹配任何空格字符。)

使用您的示例输入,上面的结果如下:

\s

请注意,捕获组乱序的原因是Name Value ---- ----- host host.name.net localpath \local\path\Client\File.txt port 22 sshkey ssh-rsa 1024 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00 remotepath /remote/archive/ password password username username 哈希表(类型为[hashtable]),其键枚举顺序是实现工件:不能保证特定的枚举顺序。

但是,随机访问捕获组效果很好;例如,$Matches将返回$Matches.port