Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Regex 通过Powershell从文本文件中提取字符串_Regex_Powershell - Fatal编程技术网

Regex 通过Powershell从文本文件中提取字符串

Regex 通过Powershell从文本文件中提取字符串,regex,powershell,Regex,Powershell,我一直在尝试使用PowerShell从.txt文件的多行中提取某些值 Host Class INCLUDE vmware:/?filter=Displayname Equal "server01" OR Displayname Equal "server02" OR Displayname Equal "server03 test" 这就是我想要的: server01 server02 server03 test 到目前为止,我有以下代码: $Regex = [Regex]::new("(?

我一直在尝试使用PowerShell从.txt文件的多行中提取某些值

Host
Class
INCLUDE vmware:/?filter=Displayname Equal "server01" OR Displayname Equal "server02" OR Displayname Equal "server03 test"
这就是我想要的:

server01
server02
server03 test
到目前为止,我有以下代码:

$Regex = [Regex]::new("(?<=Equal)(.*)(?=OR")           
$Match = $Regex.Match($String)
$Regex=[Regex]::new((?您可以使用

[regex]::matches($String, '(?<=Equal\s*")[^"]+')
输出:

server01
server02
server03 test
下面是一个完整的片段,用于读取中的文件,获取所有匹配项并保存到文件:

$newfile = 'file.txt'
$file = 'newtext.txt'
$regex = '(?<=Equal\s*")[^"]+'
Get-Content $file | 
     Select-String $regex -AllMatches | 
     Select-Object -Expand Matches | 
     ForEach-Object { $_.Value } |
     Set-Content $newfile
$newfile='file.txt'
$file='newtext.txt'

$regex='1(?您可以修改您的正则表达式以使用捕获组,该捕获组由括号表示。反斜杠仅转义引号。这允许您仅捕获您要查找的内容,然后对其进行进一步筛选。此处的捕获组自动命名为1,因为我没有提供名称。捕获组0是包括引号在内的整个匹配项s、 我切换到Matches方法,因为它包含字符串的所有匹配,而Match只捕获第一个匹配

$regex = [regex]'\"(.*?)\"'    
$regex.matches($string).groups.where{$_.name -eq 1}.value
如果要导出结果,可以执行以下操作:

$regex = [regex]'\"(.*?)\"'    
$regex.matches($string).groups.where{$_.name -eq 1}.value | sc "c:\temp\export.txt"

使用Wiktor的good RegEx,使用
Select String
直接读取文件的替代方法:

Select-String -Path .\file.txt -Pattern '(?<=Equal\s*")[^"]+' -AllMatches|
    ForEach-Object{$_.Matches.Value} | Set-Content NewFile.txt
另一个选项(PSv3+),结合了
[regex]::Matches()
-replace
操作符以获得简洁的解决方案:

$str = @'
Host
Class
INCLUDE vmware:/?filter=Displayname Equal "server01" OR Displayname Equal "server02" OR Displayname Equal "server03 test"
'@ 

[regex]::Matches($str, '".*?"').Value -replace '"'
Regex
“*?”
匹配所有
“…”
-封闭令牌;
.Value
提取它们,并
-replace'”
去除
字符

这可能并不明显,但根据我的测试,这恰好是这里答案中最快的解决方案——见下图


顺便说一句:如果
-match
操作符(只查找一个匹配项)有一个名为
-matchall
的变量,那么上面的描述将更加符合PowerShell的习惯用法,这样就可以编写:

# WISHFUL THINKING (as of PowerShell Core 6.2)
$str -matchall '".*?"' -replace '"'
请参阅GitHub上的


可选阅读:性能比较 实际上,这里的所有解决方案都很有帮助,而且可能足够快,但在某些情况下,性能必须得到优化

通常,使用
Select String
(以及一般的管道)会带来性能损失,同时提供优雅和内存高效的流处理

此外,脚本块的重复调用(例如,
{$\u0.Value}
)往往很慢,尤其是在使用
ForEach对象
Where对象
的管道中,但也在较小程度上使用
.ForEach()
Where()
收集方法(PSv4+)


在正则表达式领域,对于可变长度的look-behind表达式(例如,
(?检查+1以获得一个很好的泛化。狡辩:不需要
\
-escape
.Syntax
.where{…}
肯定有效,但对我来说更详细的形式
.where({…})出于概念上的原因,最好使用
,这样就不会有人试图使用
。其中{…}
(注意空格)顺便说一句:
Set Content
的别名
sc
已从PowerShell Core.FYI中删除,无论好坏,如果匹配可能跨越多行,请将
Get Content$file |
替换为
Get Content$file | Out String
,或者,如果您使用的是PowerShell v3或更新版本,
Get Content$file-Raw |
如果有多个
包括vmware://filter
发生了什么?我提出了一个新问题。@Arbelac您能解释一下这个问题吗?@Arbelac Try
$regex.matches($String.Split(`r`n”)。其中({$\.contains(''''')})[0])groups.where{$$\.name-eq 1}.value | sc“c:\temp\result.txt“
或者,将行选择条件更改为更安全的条件,
。其中({$\u-match'[^“]+”})
$str = @'
Host
Class
INCLUDE vmware:/?filter=Displayname Equal "server01" OR Displayname Equal "server02" OR Displayname Equal "server03 test"
'@ 

[regex]::Matches($str, '".*?"').Value -replace '"'
# WISHFUL THINKING (as of PowerShell Core 6.2)
$str -matchall '".*?"' -replace '"'
Time-Command -Count 1e3 { [regex]::Matches($str, '".*?"').Value -replace '"' },
   { [regex]::matches($String, '(?<=Equal\s*")[^"]+') | Foreach {$_.Value} },
   { [regex]::Matches($str, '\"(.*?)\"').Groups.Where({$_.name -eq '1'}).Value },
   { $str | Select-String -Pattern '(?<=Equal\s*")[^"]+' -AllMatches | ForEach-Object{$_.Matches.Value} } |
     Format-Table Factor, Command
Factor Command
------ -------
1.00   [regex]::Matches($str, '".*?"').Value -replace '"' # this answer
2.85   [regex]::Matches($str, '\"(.*?)\"').Groups.Where({$_.name -eq '1'}).Value # AdminOfThings'
6.07   [regex]::matches($String, '(?<=Equal\s*")[^"]+') | Foreach {$_.Value} # Wiktor's
8.35   $str | Select-String -Pattern '(?<=Equal\s*")[^"]+' -AllMatches | ForEach-Object{$_.Matches.Value} # LotPings'