If -match
正在返回一个全线,其含义是你的左手边-match
操作是一个array,这反过来表明您使用过Get-Content
without -Raw
,它产生的输入为array of lines, 在这种情况下-match
充当filter.
相反,将文件作为单个多行字符串读取Get-Content -Raw
; with a scalar 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
然后,您可以扩展该方法来捕获多个令牌,在这种情况下我建议using named捕获组 ((?<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
您可以扩展上面的内容来捕获all利息代币。
注意.
默认情况下不匹配\n
(换行)字符。
可选阅读:使用x
(IgnoreWhiteSpace) 选项使正则表达式更具可读性:
提取如此多的标记可能会导致难以阅读的复杂正则表达式,在这种情况下x
(IgnoreWhiteSpace
)正则表达式选项,可以提供帮助(作为内联选项,(?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
}
请注意如何使用空格使正则表达式更具可读性(将其分布在多行中)ignoredwhile 匹配时,而输入中要匹配的空格必须是escaped(例如,要匹配单个空格,\
or [ ]
, or \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
请注意,捕获组乱序的原因是$Matches
is a 哈希表(类型[hashtable]),其关键枚举顺序是一个实现工件:不保证特定的枚举顺序。
然而,随机访问捕获组效果很好;例如。,$Matches.port
将返回22
.