Я хотел бы извлечь шаблоны в соответствии с a[a-z] из длинной строки и вывести только отдельные значения. Например, для следующей строки в $x
perl -e "$x = 'abx1acy2acz3ab'";
Результаты должны быть:
ab
переменный ток
Проблема: не существует правила разделения записи/строки на массив, что упрощает извлечение шаблона.
@Predicate: мы склонны использовать хэши для моделирования наборов.





Вы получите различные шаблоны с помощью этого регулярного выражения (если вас не волнует их порядок):
(a[a-z])(?!.*\1)
Объяснение:
(a[a-z]) — соответствует букве a, за которой следует любая другая буква в диапазоне a-z. Содержимое захватывается в группе 1(?!.*\1) - отрицательный просмотр вперед, чтобы убедиться, что содержимое группы 1 не присутствует позже в строке.Спасибо за это регулярное выражение и за расширение. Как я могу распечатать каждый отдельный шаблон? perl -e "$x = 'abx1acy2acz3ab'; $x =~ /(a[a-z])(?!.*\1)/g; print $1;" печатает только ac.
Это довольно умное решение!
@giordano .. вы выполняете глобальный поиск, поэтому заверните его в цикл while perl -e '$x = "abx1acy2acz3ab"; while( $x =~ /(a[a-z])(?!.*\1)/g ) { print "$1\n" } '
Если вам когда-нибудь понадобятся уникальные данные, рассмотрите возможность использования хэша.
#!/usr/bin/perl
use strict;
use warnings;
use feature 'say';
$_ = 'abx1acy2acz3ab';
my %seen;
for (/(a[a-z])/g) {
say $_ unless $seen{$_}++;
}
Это очень интересно: можно экранировать строку с помощью for. Я этого не знал. Очень полезно.
@giordano: на самом деле вы не перебираете строку. /(...)/g вернет список совпадений, и вы перебираете этот список.
Еще один однострочный Perl
$ perl -le ' $x = "abx1acy2acz3ab" ;%kv=$x=~/(a[a-z])((?<=.))/g; $, = "\n"; print keys %kv '
ac
ab
$
с другим входом:
$ perl -le ' $x = "abxaxy2acz3ab" ; %kv=$x=~/(a[a-z])((?<=.))/g; $, = "\n"; print keys %kv '
ax
ab
ac
$
Это не работает, если входная строка, например, "abx1axy2acz3ab".
@ Дэйв .. Я только что исправил .. не могли бы вы просмотреть
Спасибо, Дэйв. Но меня кое-что удивило. Я ожидаю, что символ, совпадающий с [az], войдет в «значения» хэша.. но он печатается пустым.. Есть идеи, почему это пустая строка?
m//g вернуть список. Вы получаете 8 совпадений, каждое второе из которых пустое ( ((?<=.)) ), и они становятся вашими хэш-значениями.
Это интересный способ использовать хеш для уникальности по всем совпадениям. Так что вы заботитесь о ключах здесь, и поэтому все хорошо. (И я не получаю эту пустую строку в конце распечатки?!)
@jhnc .. если я правильно понимаю, положительный просмотр назад не потребляет никаких строк, и поэтому, если какие-либо группы захвата покрыты им, то они также не потребляют .. верно?
Если вы действительно хотите зафиксировать значения, то скобки захвата должны обходить сам шаблон (а не все утверждение): /(a[a-z])(?<=(.))/g;, для perl -E'$_ = "abxaxyaczab"; %h = /(a[a-z])(?=(.))/g; say "$_ => $h{$_}" for keys %h'
@ stack0114106 stack0114106 С Perl я стараюсь просто пробовать что-то, а не слишком много думать! :) perl -le ' $x = "abxaxy2acz3ab" ; @g=($x=~/(a[a-z])((?<=.))/g); print"<<$_>>" for @g'
@ stack0114106 Мне понравился ваш ответ здесь, спасибо за ваше время
Разве в Perl нет «набора» DS? Это, вероятно, могло бы помочь