Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/powershell/11.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 正则表达式改进建议_Regex_Powershell - Fatal编程技术网

Regex 正则表达式改进建议

Regex 正则表达式改进建议,regex,powershell,Regex,Powershell,给定一个字符串 一些文本和[A~标记]以及更多文本和[非标记]和 [另一个~token] 我需要提取“代币”以便以后替换。标记定义为两个标识符,由~分隔,并用[]括起来。我一直在做的是使用$string-match“\[.*?~..*?\]”,这很有效。而且,据我所知,我正在转义两个括号,对任何字符执行零次或多次,并强制懒惰,然后是~和相同的任何字符序列。因此,我的第一个改进是将*?替换为+?,因为我想要1个或更多,而不是0个或更多。然后我转到$string-match“\[[A-Za-z0-9

给定一个字符串

一些文本和[A~标记]以及更多文本和[非标记]和 [另一个~token]

我需要提取“代币”以便以后替换。标记定义为两个标识符,由~分隔,并用[]括起来。我一直在做的是使用
$string-match“\[.*?~..*?\]”
,这很有效。而且,据我所知,我正在转义两个括号,对任何字符执行零次或多次,并强制懒惰,然后是~和相同的任何字符序列。因此,我的第一个改进是将
*?
替换为
+?
,因为我想要1个或更多,而不是0个或更多。然后我转到
$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来完成。
最后一点澄清,令牌的数量是可变的。可能只有一个,可能是三个或四个。因此,我的解决方案必须非常灵活。

您可以使用
\w
匹配单词字符(字母、数字、下划线)。 这将导致模式
\[\w+~\w+\]

现在,您可以使用该模式创建正则表达式对象:

$rgx = [Regex]::new($pattern)
并用
replace
操作符替换该模式的所有出现:

$rgx.Replace($inputstring, $replacement)

也许还值得注意的是,正则表达式有一个
.Match
操作符,返回模式的第一次出现,还有一个
.Matches
操作符,返回模式的所有出现。

以您的示例行为例

$String = "Some text and [A~Token] and more text and [not a token] and [another~token]"
此正则表达式包含捕获组

$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 第一个令牌=一个~token第二个令牌=另一个~token 请参阅上面的RegEx解释

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

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

$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'";
}
注意:在使用
()
分组的regex部分中,这允许访问令牌的部分

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


至于
\[.*.~.*.\]
不能正常工作,因为它试图与文本
[不是令牌]和[other~令牌]
匹配并成功,就像在这个正则表达式中一样,令牌部分允许字符
][
\[^\]\[]*?~[^\]\[]*?
^
对表达式求反,使其读取:除
]之外的所有字符[
)也可以,但如果
\w
足够好的话,它不是所有大括号都可读的,你应该告诉我们。

在你定义令牌模式要求之前,我们无法帮助你。很有趣。这是一种非常不同的正则表达式和分组方法。我需要深入研究一下,才能完全理解它,但这是一个进步。谢谢。我有一个问题还有一个问题要补充。这里有什么在PS2.0中不起作用的吗?我只支持旧的(古代的)不幸的是,PowerShell。@Gordon实际上我不知道这段代码是否对2.0有效,但如果您有环境,它将很容易尝试执行。没有保证,但从
PowerShell-Version 2开始它就可以工作了。@Lotpings,谢谢验证。我挖出了我的2.0测试虚拟机并进行了验证。今晚有一些重构要做。