Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Regex 如何编写一个在每行上执行多个替换的正则表达式,除非该行以某个字符串开头?_Regex_Perl - Fatal编程技术网

Regex 如何编写一个在每行上执行多个替换的正则表达式,除非该行以某个字符串开头?

Regex 如何编写一个在每行上执行多个替换的正则表达式,除非该行以某个字符串开头?,regex,perl,Regex,Perl,我试图编写一个正则表达式,除了以两个斜杠开头的行外,它用尖括号围绕“http”URL。我想到的最好的办法是: s#^(?!/)(.*)(^\s]+)#$1#gm 这对以下两个方面非常有效: 输入: 输出: 输入:/ 输出:/ 但是,它在这里失败了: 输入: 实际输出: 所需输出: 为什么我的正则表达式不能保持匹配?我使用/g错了吗?你真的应该使用两个正则表达式;一个用于标识“注释掉的”行,另一个用于修改常规行中的http 可能有一种非标准的方法来组合这两个正则表达式或替换所有的多个(h

我试图编写一个正则表达式,除了以两个斜杠开头的行外,它用尖括号围绕“http”URL。我想到的最好的办法是:

s#^(?!/)(.*)(^\s]+)#$1#gm

这对以下两个方面非常有效:


输入:

输出:


输入:
/

输出:
/


但是,它在这里失败了:


输入:

实际输出:

所需输出:



为什么我的正则表达式不能保持匹配?我使用/g错了吗?

你真的应该使用两个正则表达式;一个用于标识“注释掉的”行,另一个用于修改常规行中的http


可能有一种非标准的方法来组合这两个正则表达式或替换所有的多个(http…)匹配项,但我不会使用它们。

对于数量不确定的表达式,您不能这样做。试试这个:

s#(http://[^\s]+)#<$1>#g unless m#^//#;
s#(http://[^\s]+)#g除非m#^/#;
这将替换该行中的所有URL,但前提是该行的前两个字符不是“/”。当然,这有点复杂,但它是有效的(我认为)


编辑:我的答案与aib的答案相同,但我有代码。

根据我的建议重写一点,并使用空格修饰符,使其真正可读。:)

s{
(?:^ |\G)#最后一场比赛的开始,所以你永远不会后退,也不会捕获。
(?!/)#没有//
(.*)#后面跟着什么
(
http://#带http://
[^\s]+#和非空格-也可以使用\s
)
}
{1}xmg;
在perl中尝试这一点,我们得到:

sub test {
    my ($str, $expect) = @_;
    my $mod = $str;
    $mod =~ s{
            (?:^|\G)       # start of the last match, so you never backtrack.
            (?!//)       # a section without //
            (.*?)        # followed by anything
            (
                http://  # with http://
                [^\s]+   # and non-spaces - you could also use \S
            )
          }
          {$1<$2>}xmg;
    print "Expecting '$expect' got '$mod' - ";
    print $mod eq $expect ? "passed\n" : "failed\n";
}

test("http://foo.com",    "<http://foo.com>");
test("// http://foo.com", "// http://foo.com");
test("foo\nhttp://a.com","foo\n<http://a.com>");

# output is 
# Expecting '<http://foo.com>' got '<http://foo.com>' - passed
# Expecting '// http://foo.com' got '// http://foo.com' - passed
# Expecting 'foo
# <http://a.com>' got 'foo
# <http://a.com>' - passed
子测试{
我的($str,$expect)=@;
my$mod=$str;
$mod=~s{
(?:^ |\G)#最后一场比赛的开始,所以你永远不会后退。
(?!/)#没有//
(.*)#后面跟着什么
(
http://#带http://
[^\s]+#和非空格-也可以使用\s
)
}
{1}xmg;
打印“预期”$expect“获得”$mod“-”;
打印$mod eq$expect?“通过”\n:“失败”\n;
}
测试(”http://foo.com",    "");
测试(“//http://foo.com", "// http://foo.com");
测试(“foo\nhttp://a.com“,“foo\n”);
#输出为
#应为“”已获得“”-已通过
#应为“//http://foo.com“有”//http://foo.com“-通过
#期待“福”
#“有”福
#“-通过

编辑:两个更改:添加“m”修饰符以确保它从一行的开头匹配,并将\G更改为(^|\G)以确保它也从一行的开头开始查看。

正则表达式被输入到一个旧函数中,该函数在一个大的多行文本块上运行。我希望我可以把它分成几行,然后按照你说的做,但是这需要大量的回归测试。主要的重构和回归测试,我应该说。@迈克-如果你需要匹配多行的开头,考虑“M”修饰符。它会使“^”和“$”匹配任何一行的开头或结尾。哦,实际上我是这样做的——当我把它变成一个SO问题时,不知怎么的,它被抹掉了。这真的很好,我可能能够自己解决最后一个小问题,但当然任何输入都是值得的:实际上它也有a/m修饰符,因为它是在一大块文本上运行的。这导致它在“foo”上失败\nhttp://a.com“…应返回“foo\n”但实际返回“foo”\nhttp://a.com“事实上,无论如何我都会接受你的答案,因为它非常适合最初提出的问题。嘿,把你的\G改成(^ | \G)和把你的1美元改成2美元似乎行得通!啊,是的:)当我更新问题时,我发现这个答案是正确的。。。给我一点,我再加上。:)
sub test {
    my ($str, $expect) = @_;
    my $mod = $str;
    $mod =~ s{
            (?:^|\G)       # start of the last match, so you never backtrack.
            (?!//)       # a section without //
            (.*?)        # followed by anything
            (
                http://  # with http://
                [^\s]+   # and non-spaces - you could also use \S
            )
          }
          {$1<$2>}xmg;
    print "Expecting '$expect' got '$mod' - ";
    print $mod eq $expect ? "passed\n" : "failed\n";
}

test("http://foo.com",    "<http://foo.com>");
test("// http://foo.com", "// http://foo.com");
test("foo\nhttp://a.com","foo\n<http://a.com>");

# output is 
# Expecting '<http://foo.com>' got '<http://foo.com>' - passed
# Expecting '// http://foo.com' got '// http://foo.com' - passed
# Expecting 'foo
# <http://a.com>' got 'foo
# <http://a.com>' - passed