正则表达式分组

时间:2016-05-08 09:16:50

标签: php regex

我想在正则表达式上探索更多内容。 Add a space on a string but counting right to left

此正则表达式的结果

preg_replace("/(?=(.{3})*(.{4})$)/", "-", "1231231234");

是:123-123-1234

现在,我正在尝试使用量词和组,但我无法让它们正常工作。

为什么这个(php)

preg_replace("/(?=(.{3})*(.{4})(.{4})$)/", "-", "1212312312345678");

和此:

preg_replace("/(?=(.{3})*(.{4}){2}$)/", "-", "1212312312345678");

两个都给了我一个8字符组作为输出

12-123-123-12345678

我可能期望第二个案例{2}的结果,但不是第一个案例的结果。

我想要的预期结果是:

12-123-123-1234-5678

1)(。{4})(。{4})=(。{8})的逻辑是什么,而不是2个不同的事件?

2)适当的分组是什么?

3 个答案:

答案 0 :(得分:2)

请注意,在这种情况下您使用lookaheads。与普通匹配不同,它们实际上并不消耗它们匹配的东西。

所以在第一个例子中,有2个零宽度匹配,第一个在第一个123之后,所以前瞻匹配1231234,第二个匹配123 },前瞻与1234匹配。您可能希望使用其中一个在线正则表达式测试程序来查看实际匹配的内容,我的选择是regex101.com

因此,对于您的示例,您必须使前瞻也匹配最后4位数(并且只有它们),实现此目的的一种方法是(?=((.{3})*(.{4}))?(.{4})$),使第一部分可选。

regex101上查看。

答案 1 :(得分:1)

(?=(.{3})*(.{4}){2}$)匹配每个3xN字符序列,末尾有2x4 = 8个字符,其中N> = 0。

要匹配末尾的每个4xN字符,其中1 <= N <= 2,或者每个3xN字符序列最后有8个字符,其中N> = 1,请使用以下内容:

preg_replace("/(?=(.{4}){1,2}$)|(?=(.{3})+.{8}$)/", "-", "1212312312345678");

答案 2 :(得分:1)

你似乎误解了正则表达式是如何运作的。让我为你分解一下:

var
  counter,k : Integer; //counters
begin
//  counter := 0;
//  k:=0;
  for counter := listview1.Items.Count-1 downto 0  do
  begin
    for k := 0 to Listbox1.items.Count-1 do
      if listview1.Items.item[counter].Caption=listbox1.items[k]  then
      begin
        listview1.Items.item[counter].Delete;
        Break;
      end;
  end;

end;

此模式会在您要插入短划线(?= lookahead assertion: the following pattern must match, but will not consume any of the text. (.{3})* matches a series of 3 characters, any number of times. In other words, this consumes characters in multiples of 3. (.{4})$ makes sure there are exactly 4 characters left. ) 的每个位置生成空匹配。这就是- 在正确位置插入破折号的原因 - 替换空字符串与插入相同。让我们一步一步地看一下,使用文本preg_replace("/(?=(.{3})*(.{4})$)/", "-", "1231231234");作为例子:

31231234

在文本中位置0处的模式匹配失败后,将在位置1处再次检查(剩余文本为 remaining text remaining pattern what happens step 0: 31231234 (.{3})*(.{4})$ (.{3})* matches one time step 1: 31234 (.{3})*(.{4})$ (.{3})* matches again step 2: 34 (.{3})*(.{4})$ (.{3})* fails to match another time step 3: 34 (.{4})$ (.{4}) fails to match -> backtrack step 5: 31234 (.{4})$ (.{4}) fails to match -> pattern failed to match, no dash will be inserted. ):

1231234

同样的事情在3个字符后再次发生,给出最终结果 remaining text remaining pattern what happens step 0: 1231234 (.{3})*(.{4})$ (.{3})* matches one time step 1: 1234 (.{3})*(.{4})$ (.{3})* matches again step 2: 4 (.{3})*(.{4})$ (.{3})* fails to match another time step 3: 4 (.{4})$ (.{4})$ matches -> dash will be inserted here, giving "3-1231234" 。换句话说,组3-123-1234指定不应在文本的最后4个字符中插入破折号。通过消耗最后4个字符,如果剩余少于4个字符,则模式无法匹配。这就是为什么(.{4})$(.{4})(.{4})$都会生成一个包含8个字符的块的原因 - 如果剩下的字符少于8个,则模式不能匹配。

要在最后8个字符中插入另一个短划线,您必须使用两组4个字符(.{4}){2}$并使其中一个可选:

.{4}