【问题标题】:DotAll and multiline RegExDotAll 和多行正则表达式
【发布时间】:2023-03-22 21:59:01
【问题描述】:

我在 Powershell 中使用 Rexex 时遇到了一点麻烦。似乎有一个实施错误或什么的。

我要使用的文本是一个 html 文件,它看起来像这样(示例 1):

<span>[Mobile: %mobile% |] Phone: %telephone% [| Fax: %faxNumber%]</span>
<Span>

问题是,由 html 编辑器引起的,我也可能会得到这样的东西(Example2):

<span>[Mobile: 

%mobile% |] Phone: %telephone% [| Fax: &nbsp;&nbsp;%faxNumber%]</span>

如您所见,我们得到了换行符和 html 转义,修复了空格 &amp;nbsp;

我的 Powershell 正则表达式如下所示:

$x = $x -ireplace '(?ms)\[(.?){7}Fax(.*?)\]', 'MyReplacement1'

还有这个

$x = $x -ireplace '(?ms)\[(.?){7}Mobile(.*?)\]', 'MyReplacement2'

基本上 [ 标记变量的开始,] 标记变量的结束。由此产生两个问题:

  1. 由于我们有两个变量,移动和传真,我使用(.?){7} 来允许一些(这里正好是 7 个)字符,并避免匹配 第一个 [ 靠近 MobileFax 附近的最后一个 ](如果我使用 (.*?) 而不是 (.?){7} 会发生这种情况)。我不确定是否有替代方法,例如,我可以在起始 [ 和变量关键字“Fax”之间允许任意数量(而不是 7 个)字符。当添加 &amp;nbsp;&amp;nbsp; 之类的内容时,这对于避免不匹配很有用(其中只有 7 个字符是不够的,就像我说的 (.*?) 会失败)。希望我能够解释它(有点难) - 如果没有:请随时提问!
  2. Powershells -replace 方法不提供设置正则表达式选项的方法,因此我必须使用 (?ms) 来设置 DotAll 和多行模式。如您所见,我在我的正则表达式模式中使用它。但是:当添加换行符时,如您在示例 2 中看到的,在词 Mobile:%mobile% 之间,正则表达式失败,没有任何东西被替换!

我非常感谢专业人士的任何帮助,甚至是正则表达式的建议,以避免我现在没有考虑的任何进一步的问题......

编辑: (例3):

<span>[Mobile: 

%mobile% |] Phone: %telephone% [| Fax: 
%faxNumber%]</span>

【问题讨论】:

  • 是的,我已经看到了。看看我对答案的评论,让我们在这里删除我们的 cmets ;)

标签: html regex powershell powershell-3.0


【解决方案1】:

DotAll 模式的技巧是使用[\s\S] 而不是.。这个字符类匹配 any 字符(因为它匹配空格和非空格字符)。 ([\w\W][\d\D] 也是如此,但空格似乎是一种约定。)

要绕过7,您可以简单地禁止在您真正想要匹配的那个之前关闭](顺便说一句,这也使得DotAll 变得不必要)。所以像这样的东西应该适合你:

\[([^\]:]*)Fax([^\]]*)\]

看起来有点难看,其实就是这个意思:

\[        # literal [
(         # capturing group 1
  [^\]:]* # match as many non-:, non-] characters as possible
)         # end of group 1
Fax       # literal Fax
(         # capturing group 2
  [^\]]*  # match as many non-] characters as possible
)         # end of group 2
\]        # literal ]

Further reading on character classes.

请注意,这些模式都不需要多行模式m(你的和我的都不是),因为它所做的只是使^$ 分别匹配行的开头和结尾。但是没有一个模式包含这些元字符。所以修饰符什么都不做。

我的控制台输出:

PS> $x = "<span>[Mobile: %mobile% |] Phone: %telephone% [| Fax: &nbsp;&nbsp;%faxNumber%]</span>"
PS> $x -ireplace '\[([^\]:]*)Mobile([^\]]*)\]', 'MyReplacement1'
<span>MyReplacement1 Phone: %telephone% [| Fax: &nbsp;&nbsp;%faxNumber%]</span>
PS> $x -ireplace '\[([^\]:]*)Fax([^\]]*)\]', 'MyReplacement2'
<span>[Mobile: %mobile% |] Phone: %telephone% MyReplacement2</span>

【讨论】:

  • 感谢您的出色回答。但是仍然存在一些问题: non-: 匹配什么?此外,当为我的两个 Powershell 命令运行该模式时,移动设备被替换得很好,但是 [|传真:%faxNumber%] 未被替换 :-(。运行在线 Rexex 验证器,您的 Regex 似乎是正确的想法。
  • @masi 我添加了: 以避免匹配潜在的some[thing: %Fax%]。但是,如果Fax 出现在括号之间的位置与您无关,您可以从字符类中删除冒号。我将再次检查我的答案是否适用于后一个示例。
  • @masi 嗯,它对我来说非常好用。 (但是,我在第一个字符类中的方括号周围进行了更改,但是对于您的输入字符串,它不应该有所作为;无论如何,请参阅我的编辑)
  • 当您导入像这样$mystring = Get-Content -Path .\test.html 这样的字符串时,而不是使用内联字符串分配 $x,其中 test.html 包含我刚刚添加到我的帖子中的内容(Example3),然后它不起作用。好像是换行的问题
  • @masi this answer 似乎有问题的原因。 Get-Content 不会产生带换行符的字符串,而是每行都有一个字符串,需要重新连接在一起,因此-ireplace 可以处理整个文件。
猜你喜欢
  • 1970-01-01
  • 2014-10-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-29
  • 1970-01-01
  • 2011-04-13
相关资源
最近更新 更多