Попробуйте URL :: Поиск . Он будет обрабатывать многие крайние случаи, такие как URL-адреса, сопровождаемые или окруженные пунктуацией:
use strict;
use warnings;
use URL::Search '$URL_SEARCH_RE';
$text =~ s{($URL_SEARCH_RE)}{<a href="$1">$1</a>}g;
Но есть и другая проблема. URL-адреса и окружающий текст должны быть экранированы HTML, если вы хотите использовать результат как HTML, но вы, конечно, не хотите экранировать HTML от вашего действительного HTML. Чтобы решить эту проблему, вы можете разбить строку на разделы URL и не-URL, экранировать оба и обернуть URL-адреса, а затем соединить их вместе. К счастью, URL :: Search имеет функцию partition_urls, предназначенную именно для этого.
use strict;
use warnings;
use utf8;
use URL::Search 'partition_urls';
use HTML::Entities;
my $text = do { local $/; <DATA> };
my $output = '';
foreach my $section (partition_urls $text) {
my $escaped = encode_entities $section->[1];
if ($section->[0] eq 'URL') {
$output .= qq{<a href="$escaped">$escaped</a>};
} else {
$escaped =~ s{(?<!\S)#([a-zA-Z0-9]+)}{<a href="https://twitter.com/hashtag/$1">#$1</a>}g;
$output .= $escaped;
}
}
print $output;
__DATA__
When a new startup enters your industry and innovates around you, winning
your customers and taking your revenues, if you fail to transform your own
business in response, are you negligent? Do shareholders have a claim against
you? https://myurl.com/blah #Governance #liability #corporatenegligence
Существует еще одно осложнение, заключающееся в том, что для использования в URL хэштеги должны быть экранированы URI, до экранирования HTML, но ограничение того, что разрешено в хэштегах, ASCII-буквами и цифрами [a-zA-Z0-9]
позволяет избежать этого проблема ... Альтернативой является то, что вам нужно снова разделить разделы без URL на хэштеги и текст без хэштега для отдельной обработки.