Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Perl: Общие вопросы > регулярные выражения


Автор: alyam 23.8.2007, 03:39
есть переменная, примерно выглядит так:
$str="слово1 слово2 слово3"
слов может быть много разных

нужно оставить только первых два.
делаю так:
$str=~/^((.*?)\s(.*?)\s)/
дальше работаю с переменной $1

а есть ли способ пооптимальней?

Автор: amg 23.8.2007, 06:44
Нежадный мультипликатор (который со знаком вопроса) - это неэффективно. Лучше так:
Код

$str=~/^(\S+)\s+(\S+)\s/; # $str не изменится, в $1 и $2 будут первое и второе слова.
$str=~/^(\S+\s+\S+)\s/; # в $1 будут первые два слова вместе с пробелами между ними.

Если же нужно изменить $str, оставив только первые два слова, то
Код

$str =~ s/^(\S+\s+\S+).*/$1/; # один вариант
$str = join ' ', (split ' ', $str)[0..1]; # другой вариант

Автор: Nab 23.8.2007, 10:11
alyam, не понятен вопрос, что нужно удалить а что оставить...
Дайте пример с большим количеством слов.

Добавлено через 8 минут и 25 секунд
Код

/^((\S+\s*){2})/

Автор: nitr 23.8.2007, 10:58
используя ответ, и как я понял вопрос, то

Код

#!/usr/bin/perl
use strict;
use warnings;

my $str = 'slovo1 slovo2 slovo3 slovo4 slovo5';
$str =~ s/^((\S+\s+){2}).*/$1/;
print $str;

Цитата

E:\>1.pl
slovo1 slovo2

Автор: Nab 23.8.2007, 11:38
Хехе, nitr, а на двух словах не сработает, а если больше, то захватит минимум один пробел в конце... а оно надо?

Автор: amg 23.8.2007, 11:55
Хехе, чтобы пробелы между 2-м и 3-м словами не захватывались, нужен третий вариант
Код

/^((\S+\s*?){2})/

Автор: nitr 23.8.2007, 13:11
а это уже иное smile ...
человек пускай сначала все уточнит, а то "пальцем в небо"

Добавлено через 1 минуту и 46 секунд
nitr, amg подправил ;)

Добавлено через 3 минуты и 21 секунду
или жестко:
Код

#!/usr/bin/perl
use strict;
use warnings;

my $str = 'slovo1 slovo2 slovo3 slovo4 slovo5';
$str =~ s/^(\S+\s+\S+).*/$1/;
print $str;

;)

Автор: alyam 23.8.2007, 13:51
а если одно слово? слов может быть от 1 до infinity
захватывать пробел в конце не нужно.
я потом объединяю эти слова через точку  join('.',split(/ /,$str)) 
может можно сразу в split задать размер массива?

Автор: amg 23.8.2007, 15:00
Цитата(alyam @  23.8.2007,  13:51 Найти цитируемый пост)
может можно сразу в split задать размер массива?
Конечно можно:
Код

$str = join '.',(split ' ',$str)[0,1];
Но если в строке всего одно слово, то перл будет ругаться. А чтобы не ругался, надо фильтр добавить:
Код

$str = join '.', grep { defined } (split ' ',$str)[0,1];

Но бы сделал так, если нужно всего два слова:
Код

$str =~ s/^(\S+)\s+(\S+).*/$1.$2/;
При этом, если в строке всего одно слово, то регулярное выражение не подойдет и строка просто останется неизмененной.


Автор: nitr 24.8.2007, 13:45
Цитата(amg @  23.8.2007,  15:00 Найти цитируемый пост)
При этом, если в строке всего одно слово, то регулярное выражение не подойдет и строка просто останется неизмененной.

Вот именно!! Истину говоришь ;)

alyam, вы вообще читаете ответы? smile или только последний smile) Вы пробуйте их тестировать, если в голове не прокручивается.

И еще раз!!! Если будете так задавать вопросы, вам вообще никто не ответит...

Автор: amg 24.8.2007, 14:20
Цитата(nitr @  24.8.2007,  13:45 Найти цитируемый пост)
Если будете так задавать вопросы, вам вообще никто не ответит...
Ну уж прямо так... Я, например, частенько отвечаю и на не очень внятные или неинтересные вопросы, просто стараюсь сделать это так, чтобы вызвать ответный поучительный флейм со стороны кого-нибудь типа тебя или других знатоков.

Автор: nitr 24.8.2007, 14:29
amg, это понятно, но у него конкретная задачка, а твои "иные", больше похожи на "перл-гольф"/JAPH smile короче "местные извращения с перл ;)", но поучительные в большинстве своем smile

Я уже описал, как данный топик называется - "пальцем в небо". Т.к. раздуваем простейшую регулярку...

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)