RegEx改进建议

时间:2018-07-02 13:03:23

标签: regex powershell

给出类似

的字符串
  

一些文本和[A〜Token]以及更多文本和[not token]和   [另一个〜令牌]

我需要提取“令牌”以供以后替换。 令牌被定义为两个标识符,它们之间用〜隔开,并用[]括起来。我一直在使用$string -match "\[.*?~.*?\]",它可以正常工作。而且,据我所知,我正在将两个方括号转义,将任何字符重复零次或多次并强制延迟,然后再进行〜,然后对任何字符序列进行相同。因此,我的第一个改进是将.*?替换为.+?,因为我想要一个或多个,而不是零或多个。然后,我移至$string -match "\[[A-Za-z0-9]+~[A-Za-z0-9]+\]",它将两个标识符限制为字母数字,这是一个很大的改进。 因此,第一个问题是: 最后一种解决方案是最好的方法,还是有待进一步改进?

此外,当前我只返回一个令牌,因此我遍历字符串,替换找到的令牌,并循环直到没有令牌。但是,我的理解是RegEx在默认情况下是贪婪的,因此我希望最后一个版本返回两个令牌,并且我可以遍历字典而不是使用While循环。 因此,第二个问题是: 我只回来一场比赛,这是什么意思?还是我误解了贪婪匹配的工作原理?

编辑: 澄清一下,我使用的是$ matches,如下所示,但仍然只能得到1。

if ($string -match "\[[A-Za-z0-9]+~[A-Za-z0-9]+\]") {
    Write-Host "new2: $($matches.count)"
    foreach ($key in $matches.keys) {
        Write-Host "$($matches.$key)"
    }
}

此外,在识别令牌时,我真的不能使用直接替换,因为存在大量潜在替换。我拿令牌,去掉方括号,然后在〜上分割,以得到前缀和后缀值,然后确定一个特定的替换值,我可以使用专用的-replace来完成。 最后澄清一下,令牌的数量是可变的。它可以是一个,也可以是三个或四个。所以我的解决方案必须非常灵活。

3 个答案:

答案 0 :(得分:2)

要列出所有标记并使用值,可以使用如下代码:

$matces = Select-String  '\[([\w]+)~([\w]+)\]' -input $string -AllMatches | Foreach {$_.matches}
foreach($value in  $matces){
    $fullToken = $value.Value;
    $firstPart = $value.Groups[1].Value;
    $secondPart = $value.Groups[2].Value;
    echo "full token found: '$fullToken' first part: '$firstPart' second part: '$secondPart'";
}

在与()分组的正则表达式部分中注意,这允许访问令牌的某些部分。

在此循环中,您可以使用fullTokenfirstPart找到要插入而不是secondPart的适当值。

至于\[.*?~.*?\]不能正常工作,因为它试图匹配并以文本[not a token] and [another~token]成功,因为在此正则表达式中,标记部分允许字符][\[[^\]\[]*?~[^\]\[]*?\]^可以使表达式取反,因此它将显示为:][以外的所有字符)也可以,但是如果\w足够好,则不能用大括号读取我们吧。

答案 1 :(得分:0)

您可以使用\w来匹配单词字符(字母,数字,下划线)。 结果就是模式\[\w+~\w+\]
现在,您可以使用该模式创建一个正则表达式对象:

$rgx = [Regex]::new($pattern)

,并使用Replace运算符替换该模式的所有出现次数:

$rgx.Replace($inputstring, $replacement)

也许值得一提的是,正则表达式有一个.Match运算符,它返回模式的第一个出现位置,还有一个.Matches运算符,它返回该模式的所有出现位置。

答案 2 :(得分:0)

以示例行

$String = "Some text and [A~Token] and more text and [not a token] and [another~token]"

此RegEx带有捕获组

$RegEx = [RegEx]"\[(\w+~\w+)\][^\[]+\[[^\]]+\][^\[]+\[(\w+~\w+)\]"
if ($string -match $RegEX){
   "First token={0} Second token={1}" -f $matches[1],$matches[2]
}

返回:

First token=A~Token Second token=another~token

请参见上面的https://regex101.com/r/tp6b9e/1

中解释的RegEx

两个标记之间的区域与否定类交替匹配 [ / ]和文字char [ / ]