简体   繁体   中英

How to get only a filename (not full path) into $1, using the PERL, regular expressions

I want to keep only the filenames (not full paths) and add the filename to some bbcode.

Here is the HTML to be converted:

<a href=/path/to/full/image.jpg rel=prettyPhoto><img rel=prettyPhoto src=/path/to/thumb/image.jpg /></a>

Notice I cannot have rel="foo" (no double quotes)..

Here is what I have in PERL, to perform the conversion:

s/\<a href=(.+?)\ rel=prettyPhoto\>\<img rel=prettyPhoto src=(.+?) \/>\<\/a\>/\[box\]$1\[\/box\]/gi;

This converts the HTML to:

[box]/path/to/image.jpg[/box]

But this is what I want as a result:

[box]image.jpg[/box]

The HTML must remain the same. So how do I change my PERL so that $1 contains only the filename?

s/\<a href=(?:.*\/)?(.+?)\ rel=prettyPhoto\>\<img rel=prettyPhoto src=(.+?) \/>\<\/a\>/\[box\]$1\[\/box\]/gi;

(?:.*\\/)?

Will match the longest part finishing by a /. The final ? makes this optional.

I don't know if it handles fringe cases, but I got this to work:

#!/usr/bin/perl

use strict;
use warnings;

my $in = '<a href=/path/to/full/image.jpg rel=prettyPhoto><img rel=prettyPhoto src=/path/to/thumb/image.jpg /></a>';

$in =~ s/\<a href=.*?([^\/]+)\ rel=prettyPhoto\>\<img rel=prettyPhoto src=(.+?) \/>\<\/a\>/\[box\]$1\[\/box\]/gi;

print $in . "\n";

However, wouldn't you rather do something like:

#!/usr/bin/perl

use strict;
use warnings;

use HTML::TokeParser;
my $p = HTML::TokeParser->new(\*DATA);

my $token = $p->get_tag("a");
my $token_attribs = $token->[1];
my $bb_code;

if ($token_attribs->{rel} eq 'prettyPhoto') {

  my $url = $token_attribs->{href};
  my @split_path = split(m'/', $url);

  $bb_code = '[box]' . $split_path[-1] . '[/box]';
}

print $bb_code . "\n";
__DATA__
<a href=/path/to/full/image.jpg rel=prettyPhoto><img rel=prettyPhoto src=/path/to/thumb/image.jpg /></a>

using an HTML parser (like HTML::TokeParser , which has examples in the documentation) to find the url for you? Much better than relying on regexing the HTML by hand.

I suggest you use the right tools for the job, like these:

use HTML::PullParser;
use URI;

die '' . $! || $@ 
    unless my $p = HTML::PullParser->new(
      doc         =>  $doc_handle
    , start       => 'tag, attr'
    , report_tags => ['a']
    );

my @file_names;
while ( my $t = $p->get_token ) { 
    next unless $t    and my ( $tag_name, $attr ) = @$t;
    next unless $attr and my $href = $attr->{href};
    next unless my $uri = URI->new( $attr->{href} );
    next unless my $path = $uri->path;
    push @file_names, substr( $path, rindex( $path, '/' ) + 1 );
    # or it's safe to use a regex here:
    # push @file_names, $path =~ m{([^/]+)$};
}

Data::Dumper->Dump( [ \@file_names ], [ '*file_names' ] );

Friends don't let friends parse HTML with regexes.

Don't capture the whole thing. Use non-capturing groups with (?:...) . This way you can further subdivide the part that you match and the part that you capture.

这显然在正则表达式中不起作用,但是您可以在$ 1上运行split函数并获取结果数组的最后一个元素。

关于什么:

s/\<a href=.*\/(.+?)\ rel=prettyPhoto\>\<img rel=prettyPhoto src=(.+?) \/>\<\/a\>/\[box\]$1\[\/box\]/gsi;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM