Regex URL的Perl正则表达式替换

Regex URL的Perl正则表达式替换,regex,perl,url,Regex,Perl,Url,我试图使用一个复杂的正则表达式来匹配文本体中的URL。目的是在文本中对URL进行分隔 我想做下面的事情 perl -pe 's/regex/left $1 right/g;' inputfile 这将用单词left和right包围的匹配值替换所有出现的正则表达式。这只是一个简单的示例来说明这一点-真实场景中有大量-e表达式,我希望为这个特定的匹配目的添加另一个表达式 正则表达式与URL匹配。我意识到匹配URL非常困难,可能不可能识别所有可能的URL,但合理的近似值就可以了。我已经找到了一个这样

我试图使用一个复杂的正则表达式来匹配文本体中的URL。目的是在文本中对URL进行分隔

我想做下面的事情

perl -pe 's/regex/left $1 right/g;' inputfile
这将用单词
left
right
包围的匹配值替换所有出现的正则表达式。这只是一个简单的示例来说明这一点-真实场景中有大量
-e
表达式,我希望为这个特定的匹配目的添加另一个表达式

正则表达式与URL匹配。我意识到匹配URL非常困难,可能不可能识别所有可能的URL,但合理的近似值就可以了。我已经找到了一个这样的近似值


但是,我不能让正则表达式在上述perl结构中工作。我尝试过使用不同于
/
的分隔符,例如
~
,但没有成功。

由于另一个问题,我找到了这个问题的答案。这个URL比我以前尝试的要简单得多,但在我测试过的简单案例中似乎可以工作

perl -i -pe 's,(http.*?://([^\s)\"](?!ttp:))+),left $& right,g;' myfile
的附录B给出了解析URI的正则表达式

B.使用正则表达式解析URI引用 如第4.3节所述,通用URI语法不足以消除某些形式URI组件的歧义。由于该节中描述的“贪婪算法”与POSIX正则表达式使用的消歧方法相同,因此使用正则表达式解析URI引用的潜在四个组件和片段标识符是自然和常见的

下面一行是将URI引用分解为其组件的正则表达式

^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
 12            3  4          5       6  7        8 9
上面第二行中的数字仅用于帮助可读性;它们表示每个子表达式(即每个成对括号)的参考点。我们将子表达式n的匹配值称为
$
。例如,将上述表达式与

http://www.ics.uci.edu/pub/ietf/uri/#Related
导致以下子表达式匹配:

$1 = http:
$2 = http
$3 = //www.ics.uci.edu
$4 = www.ics.uci.edu
$5 = /pub/ietf/uri/
$6 = <undefined>
$7 = <undefined>
$8 = #Related
$9 = Related
相反,我们可以使用第5.2节步骤7中的算法从其组件重新创建URI引用

正则表达式在Perl中可以直接使用,如

if ($uri =~ m!^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?!) {
    my($host,$path) = ($4,$5);
    print "$host => $path\n";
}
正则表达式量词中的贪婪可能会使此模式难以与
s//
一起使用,因为它将消耗尽可能多的文本,可能会超出未标记的URI边界

更直接适用的是CPAN上提供的模块。左右边界的划分就像

#! /usr/bin/env perl

use strict;
use warnings;

use URI::Find;

my $finder = URI::Find->new(sub {
    my(undef,$found) = @_;
    "LEFT $found RIGHT";
});

while (<>) {
    $finder->find(\$_);
    print;
}
#/usr/bin/env perl
严格使用;
使用警告;
使用URI::Find;
my$finder=URI::Find->new(子系统){
我的(未定义,$found)=@;
“左$found RIGHT”;
});
而(){
$finder->find(\$\);
印刷品;
}
输出:

$ cat input This is a plain text input suitable for an answer to a question on http://stackoverflow.com In particular, the question is available at http://stackoverflow.com/q/15233535/123109 and the answer at http://stackoverflow.com/a/15234378/123109 $ ./mark-uris input This is a plain text input suitable for an answer to a question on LEFT http://stackoverflow.com RIGHT In particular, the question is available at LEFT http://stackoverflow.com/q/15233535/123109 RIGHT and the answer at LEFT http://stackoverflow.com/a/15234378/123109 RIGHT $cat输入 这是一个纯文本输入,适用于 对一个问题的回答http://stackoverflow.com 具体而言,该问题可在 http://stackoverflow.com/q/15233535/123109 答案是什么 在http://stackoverflow.com/a/15234378/123109 $/标记URI输入 这是一个纯文本输入,适用于 对左边一个问题的回答http://stackoverflow.com 正确的 具体而言,该问题可在 左边http://stackoverflow.com/q/15233535/123109 正确与答案
左边http://stackoverflow.com/a/15234378/123109 右匹配URL的正则表达式很容易变得不可管理:

my @urls;
while ($body =~ m{
    (
        (ftp|https?):\/\/
        ([a-z0-9\-_]+(:[^@]+)?\@)?
        (
            ([a-z0-9\.\-]+)\.([a-z\.]{2,6})
            |
            ([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})
        )
        (:[0-9]{2,5})?
        (
            [a-z0-9\.\-_/\+\%&;\:,\=\!@\(\)\[\]~\'\"]*
            [a-z0-9\.\-_/\+\%&;\:,\=\!@\(\)\[\]~]+
        )
        (\?[a-z0-9\.\-_/\+\%&;\:,\=\!@\(\)\[\]~]*)?
        (\#[a-z0-9\.\-_/\+\%&;\:,\=\!@\(\)\[\]~]*)?
    )
}gisx) {
    push @urls => $1;
}
输入:

因此,要解决您的具体案例:

perl -MRegexp::Common=URI -pe 's/($RE{URI}{HTTP})/left $1 right/gos' inputfile

可能的重复有很多类似的问题,但我不认为这是重复的,因为我在问如何在Perl命令行(即作为
-e
表达式)上以特定的方式使用特定的复杂正则表达式(作者说它在Perl中工作)。我已经发布了我能想出的最好的答案,但会对任何人展示使用重量级正则表达式作为<代码> perl -pe < /c>表达式的人感兴趣。没有考虑用户名/密码;e、 g.
ftp://username@主机名/
ftp://username:password@主机名/
use Regexp::Common qw(URI);
my @urls;

while ($body =~ m{($RE{URI}{HTTP})}gos) {
    push @urls => $1;
}
perl -MRegexp::Common=URI -pe 's/($RE{URI}{HTTP})/left $1 right/gos' inputfile