2

我想知道是否可以使用一组正则表达式搜索/替换模式来替换包含在 2 个标记内的字符串中特定字符的所有出现。

例如,是否可以将 TOKEN1 和 TOKEN2 之间的文本的所有句点替换为空格,如下例所示?

以便:

TOKEN1:Run.Spot.run:TOKEN2

改为:

TOKEN1:Run Spot run:TOKEN2

注意:正则表达式需要能够替换任何文本中的任意数量的句点,而不仅仅是上面的特定模式。

我更多地问这个问题是出于我个人的知识,因为这是我过去多次想要通过各种正则表达式实现做的事情。然而,在这种特殊情况下,正则表达式将在 php.ini 中。

我对 php 解决方法不感兴趣,因为我知道该怎么做。我正在尝试扩展我对正则表达式的了解。

谢谢

4

3 回答 3

4

一种方法:

$pattern = '~(?:TOKEN1:|\G(?!^))(?:[^:.]+|:(?!TOKEN2))*\K\.~';
$replacement = ' ';
$subject = 'TOKEN1:Run.Spot.run:TOKEN2';
$result = preg_replace($pattern, $replacement, $subject);

图案细节:

~                  # pattern delimiter
(?:                # open a non capturing group
    TOKEN1:        # TOKEN1:
  |                # OR
    \G(?!^)        # a contiguous match but not at the start of the string
)                  # close the non capturing group
(?:                # open a non capturing group
    [^:.]+         # all that is not the first character of :TOKEN2 or the searched character
  |                # OR
    :(?!TOKEN2)    # The first character of :TOKEN2 not followed by the other characters
)*                 # repeat the non capturing group zero or more times
\K                 # reset the match
\.                 # the searched character
~                  # delimiter

这个想法是用来\G强制每个匹配是TOKEN1:或与先前匹配连续的匹配。

注意:默认行为类似于 html 标记(在关闭之前始终处于打开状态)。如果:TOKEN2未找到,所有\.字符将被替换TOKEN1:

于 2013-09-02T22:22:43.333 回答
0

我认为最好的方法是写这样的东西:

$result =
    preg_replace_callback(
        '/(TOKEN1:)([^:]+)(:TOKEN2)/g',
        function ($matches) {
            return $matches[0]
                   . preg_replace('/[.]/g', ' ', $matches[1])
                   . $matches[2];
        },
        'TOKEN1:Run.Spot.run:TOKEN2'
    );

(免责声明:未经测试。)

于 2013-09-02T22:49:43.453 回答
0

最简单的是,您需要一个转义的 ( \) 句点(因为句点通常匹配任何字符)作为您的模式 : \.,并且您可以用空格替换它:

这将替换.with的所有实例

但是,根据您的评论,您似乎要求使用正则表达式替换单词字符之间的所有句点:

(?<=\w)\.(?=\w)

您需要对单词字符进行正(零宽度非捕获)lookbehind: (?<=\w),您的转义句点(\.)和对单词字符进行正(零宽度非捕获)lookahead: (?=\w)。用空格替换它会得到你想要的结果。

如果您只想替换标记之间的句点,您可以在前面加上一个肯定的lookbehind:(?<=TOKEN1:.+)并附加一个肯定的lookahead: (?=.+TOKEN2),所以完整的正则表达式将是:

(?<=TOKEN1:.+)(?<=\w)\.(?=\w)(?=.+TOKEN2)

如果在开始令牌之后和/或在结束令牌之前立即出现一段时间并且您不想替换它们,则您可能需要对此进行细化。

于 2013-09-02T22:53:47.563 回答