Powershell正则表达式匹配特定的文本顺序,并仅在结果中包含它们

时间:2017-09-10 09:46:45

标签: regex powershell

我试图在Select-String Commandlet中为powershell找到工作正则表达式,查找特定文本,该文本被标记为查看文本的开头,并从此处查找其他特定文本,直到找到最后一个文本。

带文字的文件示例:

[Begin Of_Header]
Some.Text="Text"
Some.Text="Text"
Serial=0X94PA
Some.Text="Text"
Some.Text="Text"
Timer=0
Some.Text="Text"
Some.Text="Text"
Tag.SM=00
Some.Text="Text"
Some.Text="Text"
Some.Text="Text"
Some.Text="Text"
Tag.OM=00
Some.Text="Text"
Some.Text="Text"
Some.Text="Text"
Tag.UC=00
Some.Text="Text"
Some.Text="Text"
Some.Text="Text"
Events=pd_exf1
Some.Text="Text"
Some.Text="Text"
Some.Text="Text"
Acp="My looking dynamic text"
Some.Text="Text"
Some.Text="Text"
Dir=6
Some.Text="Text"
Some.Text="Text"
WG=100
Some.Text="Text"
Some.Text="Text"
H=95.5
Some.Text="Text"
Some.Text="Text"

[Begin Of_Header]
Serial=0XZZZ
Timer=0
Some.Text="Text"
Some.Text="Text"
Tag.OM=00
Tag.UC=00
Some.Text="Text"
Some.Text="Text"
Events=pd_exf1
Acp="My looking dynamic text"
Dir=6
WG=100
H=95.5


[Begin Of_Header]
Serial=0XPPPP
Timer=0
Tag.SM=00
Some.Text="Text"
Some.Text="Text"
Tag.OM=00
Tag.UC=00
Some.Text="Text"
Some.Text="Text"
Events=pd_exf1
Acp="My looking dynamic text"
Dir=6
WG=100
H=95.5

在这种情况下,它应该寻找静态字 [Begin Of_Header] ,从这一点开始以 Serial = 开头并以 Acp =&#34;我看起来动态的文字&#34; 。并且Acp =可以具有各种值+序列。如果缺少值,例如缺少 Tag.SM = 00 ,则跳过此组中的搜索并跳转到下一个 [Begin Of_Header] 并再次开始分析。< / p>

结果应该是这样的:

[Begin Of_Header]
Serial=0X94PA
Timer=0
Tag.SM=00
Tag.OM=00
Tag.UC=00
Events=pd_exf1
Acp="My looking dynamic text"

[Begin Of_Header]
Serial=0XPPPP
Timer=0
Tag.SM=00
Tag.OM=00
Tag.UC=00
Events=pd_exf1
Acp="My looking dynamic text"

我找到了类似的here,但并没有完全按照我的意愿行事。

此功能也不会按预期工作,因为它不会排除损坏的完全匹配顺序:

Select-String -LiteralPath "C:\myfile.txt" -Pattern "\[Begin Of_Header\]|Serial=|Timer=|Tag.SM=|Tag.OM=|Tag.UC=|Events=|Acp=" | Select-Object LineNumber,Line

2 个答案:

答案 0 :(得分:0)

如果您愿意尝试除正则表达式之外的其他内容。我只是创建一个具有一些if条件的数组并抓住我需要的东西。

像这样......

不确定这是否是最有效的代码,但它有效..

$content = get-content "C:\myfile.txt"

$serial = @()
$timer = @()
$sm = @()
$om = @()
$uc = @()
$events = @()
$acp = @()

Foreach($line in $content){
    If ($line -match "Serial="){$serial += $line}
    If ($line -match "Timer="){$timer += $line}
    If ($line -match "Tag.SM="){$sm += $line}
    If ($line -match "Tag.OM="){$om += $line}
    If ($line -match "Tag.UC="){$uc += $line}
    If ($line -match "Events="){$events += $line}
    If ($line -match "Acp="){$acp += $line}
}

"[Begin Of_Header]"
$serial[0]
$timer[0]
$sm[0]
$om[0]
$uc[0]
$events[0]
$acp[0]

"[Begin Of_Header]"
$serial[2]
$timer[2]
$sm[2]
$om[2]
$uc[2]
$events[2]
$acp[2]

答案 1 :(得分:0)

正则表达式很复杂,但由于元素的顺序是固定的,我没有看到问题。

$Header = '[Begin Of_Header]'
$RE = [RegEx]'(?smi)(^Serial=.*?$).*(^Timer=.+?$).*(^Tag\.SM=.+?$).*(^Tag\.OM=.+?$).*(^Tag\.UC=.+?$).*(^Events=.+?$).*(^Acp=.+?$)'

(Get-Content .\myfile.txt -raw) -split [RegEx]::Escape($Header)|
    Select-String $RE | ForEach-Object{
        $Header
        for($i=1;$i -lt 8;$i++){$_.matches.groups[$i].value}
        ""
    }

示例输出:

> Q:\Test\2017\09\10\SO_46139332.ps1
[Begin Of_Header]
Serial=0X94PA
Timer=0
Tag.SM=00
Tag.OM=00
Tag.UC=00
Events=pd_exf1
Acp="My looking dynamic text"

[Begin Of_Header]
Serial=0XPPPP
Timer=0
Tag.SM=00
Tag.OM=00
Tag.UC=00
Events=pd_exf1
Acp="My looking dynamic text"
  • 标题用于将文件内容拆分为块以分别与RE匹配
  • (?smi)建议RE使用

    • s修饰符:单行。 Dot匹配换行符

    • m修饰符:多行。导致^和$匹配每行的开头/结尾(不仅是字符串的开头/结尾)

    • i修饰符:不敏感。不区分大小写的匹配
  • (^Serial=.*?$).*

    • 第一捕获组(^ Serial =。*?$)
      ^断言行开头的位置
      Serial =匹配字符Serial =字面意思(不区分大小写)
      。*?
      。匹配任何角色 *?量词 - 在零和无限时间之间匹配,尽可能少,根据需要扩展(懒惰) $断言行尾的位置
      *
      匹配任何角色 *量词 - 在零和无限次之间匹配,尽可能多次,根据需要回馈(贪婪)