Как получить только имя файла (не полный путь) в $ 1, используя PERL, регулярные выражения - PullRequest
1 голос
/ 03 марта 2011

Я хочу сохранить только имена файлов (не полные пути) и добавить имя файла в некоторый bbcode.

Вот HTML-код для преобразования:

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

Обратите внимание, у меня не может быть rel = "foo" (без двойных кавычек) ..

Вот что у меня есть в PERL для выполнения преобразования:

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

Это преобразует HTML в:

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

Но это то, что я хочу в результате:

[box]image.jpg[/box]

HTML должен оставаться прежним. Так как мне изменить мой PERL, чтобы в $ 1 содержалось только имя файла?

Ответы [ 6 ]

1 голос
/ 03 марта 2011

Я предлагаю вам использовать правильные инструменты для работы, например:

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' ] );

Друзья не позволяют друзьям анализировать HTML с регулярными выражениями.

1 голос
/ 03 марта 2011

Я не знаю, обрабатывает ли он несколько случаев, но я заставил это работать:

#!/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";

Тем не менее, вы бы предпочли сделать что-то вроде:

#!/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>

использовать HTML-анализатор (например, HTML::TokeParser, у которого есть примеры в документации), чтобы найти URL для вас?Намного лучше, чем полагаться на регулярное выражение HTML вручную.

1 голос
/ 03 марта 2011
s/\<a href=(?:.*\/)?(.+?)\ rel=prettyPhoto\>\<img rel=prettyPhoto src=(.+?) \/>\<\/a\>/\[box\]$1\[\/box\]/gi;

(?:.*\/)?

Будет соответствовать самой длинной части, заканчивающейся на /. Финал ? делает это необязательным.

0 голосов
/ 03 марта 2011

А как же:

s/\<a href=.*\/(.+?)\ rel=prettyPhoto\>\<img rel=prettyPhoto src=(.+?) \/>\<\/a\>/\[box\]$1\[\/box\]/gsi;
0 голосов
/ 03 марта 2011

Это очевидно не работает внутри регулярного выражения, но вы можете просто запустить функцию split на $ 1 и получить последний элемент полученного массива.

0 голосов
/ 03 марта 2011

Не пойми все это.Используйте группы без захвата с (?:...).Таким образом, вы можете дополнительно подразделить часть, которую вы соответствуете, и часть, которую вы захватили.

...