Regex 需要贪婪量词的帮助吗

Regex 需要贪婪量词的帮助吗,regex,perl,greedy,Regex,Perl,Greedy,我正在用Perl做一个简单的搜索和替换,但是我需要一些帮助。以下是文件中的行: 1001(seperator could be "anything")john-1001(seperator could be "anything")mark 1001(seperator could be "anything")mark-1001(seperator could be "anything")john 我想给john分配一个新的用户ID,比如2001。这就是我想要的结果: 2001($1)john-

我正在用Perl做一个简单的搜索和替换,但是我需要一些帮助。以下是文件中的行:

1001(seperator could be "anything")john-1001(seperator could be "anything")mark
1001(seperator could be "anything")mark-1001(seperator could be "anything")john
我想给john分配一个新的用户ID,比如2001。这就是我想要的结果:

2001($1)john-1001-mark
1001-mark-2001($1)john

当john是第一个时,我的正则表达式工作得很好,但当mark是第一个时,它会出错。

如果不知道分隔符可以是什么——哪些字符、有多少个字符,等等,回答这个问题几乎是不可能的。非贪婪的任意分隔符如下所示:

s/\b1001\b(?=.*?\bjohn\b)/2001/
当匹配中间字符的最小数目时,后跟“john”将替换“1001”
*?
*
的非贪婪版本。但是,如果可能,正则表达式总是匹配的,所以这仍然是匹配的

1001-mark-1001-john
换句话说,这不仅仅是一个贪婪的问题。我们需要至少定义三件事中的一件:

  • 分隔符可以包含的字符
  • 分隔符不能包含的字符
  • 分隔符中的字符数
如果我们假设分隔符不能包含“word”字符(a-z、0-9和下划线),我们可以得到一些可行的结果:

s/\b1001\b(?=\W+?\bjohn\b)/2001/

已知部分(“1001”和“john”)被绑定以防止它们与这些子字符串匹配其他字符串。(感谢Chas注意到边缘情况。)

如果不知道分隔符可以是什么,就几乎不可能回答这个问题——哪些字符,多少个字符,等等。非贪婪的任意分隔符如下所示:

s/\b1001\b(?=.*?\bjohn\b)/2001/
当匹配中间字符的最小数目时,后跟“john”将替换“1001”
*?
*
的非贪婪版本。但是,如果可能,正则表达式总是匹配的,所以这仍然是匹配的

1001-mark-1001-john
换句话说,这不仅仅是一个贪婪的问题。我们需要至少定义三件事中的一件:

  • 分隔符可以包含的字符
  • 分隔符不能包含的字符
  • 分隔符中的字符数
如果我们假设分隔符不能包含“word”字符(a-z、0-9和下划线),我们可以得到一些可行的结果:

s/\b1001\b(?=\W+?\bjohn\b)/2001/
已知部分(“1001”和“john”)被绑定以防止它们与这些子字符串匹配其他字符串。(感谢Chas注意到边缘情况。)

尝试以下方法:

#!/usr/bin/perl

use strict;
use warnings;

while (<DATA>) {
    s/\b1001-john\b/2001-john/;
    print;
}

__DATA__
1001-john-1001-mark
1001-mark-1001-john
11001-john
1001-johnny
sexeger的基本思想是反转字符串,使用反转的正则表达式,然后反转结果。问题是,
*?
给出了第一个匹配中最短的字符串,而不是可能的最短字符串。当然,
“1001-mark-2001-john”
仍有问题,因为
*?
将匹配
“-mark-2001-”
。最好确定文件格式并对其进行解析,而不是尝试使用正则表达式。

尝试以下方法:

#!/usr/bin/perl

use strict;
use warnings;

while (<DATA>) {
    s/\b1001-john\b/2001-john/;
    print;
}

__DATA__
1001-john-1001-mark
1001-mark-1001-john
11001-john
1001-johnny

sexeger的基本思想是反转字符串,使用反转的正则表达式,然后反转结果。问题是,
*?
给出了第一个匹配中最短的字符串,而不是可能的最短字符串。当然,
“1001-mark-2001-john”
仍有问题,因为
*?
将匹配
“-mark-2001-”
。与其尝试使用正则表达式,不如确定文件格式并对其进行解析。

它可能类似于

$s = '1001-mark-1001-john';
$s =~ s/(\d+)(-john)/2001$2/i;
print $s;

可能是这样的

$s = '1001-mark-1001-john';
$s =~ s/(\d+)(-john)/2001$2/i;
print $s;

我从你的评论中猜测分隔符并不总是连字符,事实上可以是多个字符

对于这种情况,请尝试:

s/\d+([^\d]*)john/2001$1john/

这将在更换过程中保持“1001”和“john”之间的分离器完好无损。请注意,分隔符中不允许有数字,因此即使在“mark”之后出现“john”(因为“-mark-1001-”不是一个有效的分隔符)时,这也会起作用。

根据您的评论,我猜测分隔符并不总是连字符,实际上可以是多个字符

对于这种情况,请尝试:

s/\d+([^\d]*)john/2001$1john/

这将在更换过程中保持“1001”和“john”之间的分离器完好无损。请注意,分隔符中不允许有数字,因此即使在“mark”之后出现“john”(因为“-mark-1001-”不是有效的分隔符)时,也可以使用此分隔符。

是否要发布您正在使用的正则表达式?我们需要有关数据以及您试图查找和替换的固定/可变部分的更多信息。所有的ID都是四位数吗?“—”总是分隔符吗?你知道号码(1001)和姓名(john)吗?每行是否总是有两个用户,以-分隔?当你说分隔符变化很大时,你是什么意思?关键是对分隔符有足够的了解,以便能够将其与数据区分开来;e、 g.“1001;foo-1000;bar-999;baz”是foo/baz记录(带分隔符“;”和“;bar-999;”)还是bar/baz记录(带分隔符“;foo-1000;”和“;”)?要发布您正在使用的正则表达式吗?我们需要有关数据以及您试图查找和替换的固定/可变部分的更多信息。所有的ID都是四位数吗?“—”总是分隔符吗?你知道号码(1001)和姓名(john)吗?每行是否总是有两个用户,以-分隔?当你说分隔符变化很大时,你是什么意思?关键是对分隔符有足够的了解,以便能够将其与数据区分开来;e、 g.“1001;foo-1000;bar-999;baz”是foo/baz记录(带分隔符“;”和“;bar-999;”)还是bar/baz记录(带分隔符“;foo-1000;“和”;”)?我的问题是,我使用(*)来获取userID和“john”之间的任何内容,因为它变化很大。但是当“马克”第一次出现的时候,它自然就搞砸了。。我的问题是,我使用(.*)获取userID和“john”之间的任何内容,因为它变化很大。但是当“马克”第一次出现的时候,它自然就搞砸了。。那么我该怎么做呢?这个答案错了吗?如果你要否决它,请告诉我还有什么可以做得更好;我不是正则表达式大师(你可能已经猜到了)。这个答案错了吗?如果你是