我在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分配一个新的userID,比如2001.所以这就是我想要的结果:
2001($1)john-1001-mark
1001-mark-2001($1)john
当john第一次出现时,我的正则表达式正常,但是当mark是第一次时,它就搞砸了。
答案 0 :(得分:3)
几乎不可能在不知道分隔符是什么的情况下回答这个问题 - 哪些字符,多少个字符等等。非贪婪的任意分隔符看起来像这样:
s/\b1001\b(?=.*?\bjohn\b)/2001/
当匹配最小中间字符数时,这将替换“1001”后跟“john”。 .*?
是.*
的非贪婪版本。但是,正则表达式总是匹配,所以这仍然匹配
1001-mark-1001-john
换句话说,这不仅仅是贪婪问题。我们需要至少定义以下三个方面之一:
如果我们假设分隔符不能包含“word”字符(a-z,0-9和下划线),我们可以得到一些可行的东西:
s/\b1001\b(?=\W+?\bjohn\b)/2001/
已知部分(“1001”和“john”)被限制以防止它们与这些子串匹配其他字符串。 (感谢Chas注意到边缘情况。)
答案 1 :(得分:3)
试试这个:
#!/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
\b
阻止其匹配"1001-john"
以外的内容。有关详细信息,请参阅perldoc perlre
的“断言”部分。
嗯,听起来你需要一个sexeger:
#!/usr/bin/perl
use strict;
use warnings;
while (<DATA>) {
my $s = reverse;
$s =~ s/\bnhoj(.*?)1001\b/nhoj${1}1002/;
$s = reverse $s;
print $s;
}
__DATA__
1001-john-1001-mark
1001-mark-1001-john
11001-john
1001-johnny
性爱的基本思想是反转字符串,使用反向正则表达式,然后反转结果。问题是.*?
为您提供了第一场比赛中最短的字符串,而不是最短的字符串。当然,由于"1001-mark-2001-john"
与.*?
匹配,"-mark-2001-"
仍有问题。最好确定文件格式是什么并解析它而不是尝试使用正则表达式。
答案 2 :(得分:0)
我猜测你的评论中的分隔符并不总是一个连字符,实际上可能不止一个字符。
对于这种情况,请尝试:
s/\d+([^\d]*)john/2001$1john/
这将在更换过程中保持“1001”和“john”之间的分隔符不变。请注意,分隔符中不允许任何数字,因此即使在“标记”之后出现“john”(因为“-mark-1001-”不是有效的分隔符),这也会起作用。
答案 3 :(得分:-1)
它可能类似
$s = '1001-mark-1001-john';
$s =~ s/(\d+)(-john)/2001$2/i;
print $s;