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


Автор: s_a_s_h_a 24.8.2004, 17:23
Программисты, помогите пожалуйста советом. Надо придумать алгоритм, который усекал бы строки следующим образом.

Например, у нас есть десяток строчек

ааааа ббббб вввввв ::: гггг
ааааа ддддд ааааа
ааааа ЖЖЖ вылылжд ::: ---- оалвоалд
.............................................................
ааааа::::оадвоалды

мне надо получить эти строчки без ааааа.
Т.е. обрезать одинаковую последовательность символов (только сначала, из середины и конца не надо).

Самое плохое что этих строк много.

Автор: GoodBoy 24.8.2004, 17:28
Код
foreach my $line (@lines) {
   $line =~ s/(^aaaaa|aaaaa$)//;
}

Может так???

Автор: HalkaR 24.8.2004, 17:37
Нет, похоже имелось в виду, что надо удалять любую последовательность одинаковых символов из начала.

Код
Глюки

Автор: GoodBoy 24.8.2004, 17:52
HalkaR :-)))))))))))
Так ты удалишь ВСЮ строку!!! :-)))))) Читаем регэксп: от начала строки (^) любой символ (.) повторяющийся 1 и более раз (+?)... :-))))) Это выражение соответствует всей строке!

Автор: Secandr 24.8.2004, 20:25
HalkaR
тут нужны обратные сслылки:
/(.)(\\1)+/\\1/gi
если я синтаксис не забыл

Автор: korob2001 24.8.2004, 22:08
Может такой вариант подойдёт?
Код

#!/usr/bin/perl
use locale;
$str = 'ааааа ббббб вввввв ::: гггг';
$str =~ s/^([a-zA-ZА-Яа-я])\1+(?:\s+)?//;
print $str;

или так:
Код

#!/usr/bin/perl
use locale;
$str = 'ааааа ббббб вввввв ::: гггг';
$str =~ s/^([a-zA-ZА-Яа-я])(?:\1+)?(?:\s+)?//;
print $str;

Автор: Secandr 25.8.2004, 08:15
korob2001
А мочему [a-zA-ZА-Яа-я]? А если я напишу так
Цитата
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
Лучше уж точка.
И почему бы не использовать модификатор g - что бы за раз делать все возможные замены?

Я бы так сделал:
Код
#!/usr/bin/perl
use locale;
$str = 'ааааа ббббб вввввв ::: гггг';
$str =~ s/(.)\1+/\1/g;
print $str;

{заменить все повторяющиеся символы одним}
Добавлено @ 08:19
Перечитал пост, понял, нужно только из начала и один раз smile.gif
Добавлено @ 08:21
Если ааааа - определёной длинны, то можно просто:
Код
print substr $line,6;

Автор: s_a_s_h_a 25.8.2004, 08:46
Всем спасибо за ответы, но я наверное плохо объяснил. Попытаюсь еще раз.
1) у нас есть несколько строк.
2) каждая строка - произвольный набор символов.
3) надо определить встречается ли в каждой из этих строк одна и та же последовательность символов и если да, то удалить ее из каждой строки.

Автор: Secandr 25.8.2004, 09:32
Объясняешь ты не ахти...

Тебе нужно следующее:
1. прочитать файл построчно
2. для каждой строки найти символы до пробела $line=~m/^([^ ]+)[ ]/
3. Если это первая строка запомнить $1 в $first, иначе сравнить $1 и $first
4. Если $1 и $first не совпали, значит не все строки начинаются с одинаковых символов, выходим из цикла и ставим флаг $no=1;
5. После окончания цикла проверяем $no==1, если нет, то читаем весь файл и выризаем первые символы.


Добавлено @ 09:32
я правильно понял?

Автор: HalkaR 25.8.2004, 09:34
GoodBoy , и правда глючу sad.gif
Имелось в виду

Код
foreach my $line (@lines) {
  $line =~ s/^(.+?) (.+?)$/$2/;
}

Автор: s_a_s_h_a 25.8.2004, 09:47
Secandr, почти. Только вот не до пробела. Пример:

1)
Название сайта :: раздел :: подраздел 1
..................................................................
Название сайта :: раздел :: подраздел N

результат должен быть:

подраздел 1
....................
подраздел N

2)
а может быть так:

Название сайта -- раздел 1
..................................................................
Название сайта -- раздел N

результат должен быть

раздел 1
....................
раздел N

и т.п.

Т.е. разделители неизвестны.

Автор: Secandr 25.8.2004, 09:53
если ничего не известно, то сделать ничего нельзя.

Тут нужны допущения:
+ пусть название "раздел 1" содержит пробелы, буквы и цифры

тогда
Код
$line=~s/^(.*)[^a-zA-Zа-яА-Я0-9 ]+([^a-zA-Zа-яА-Я0-9 ]+)$/\2/;
print "обрезали $1";

a-zA-Zа-яА-Я0-9 - сюда нужно добавить все не разделители.
Добавлено @ 09:54
или разделитель -это любой символ повторяющийся два раза, ....

нужно определиться что есть разделитель, вернее чем он может быть.

Автор: s_a_s_h_a 25.8.2004, 10:05
Secandr, строки, которые мне нужно разобрать - это то, что получено из HTML-страниц, а именно: из тега <title>. У каждого создателя сайта свой вкус и стиль, так что я не могу представить все варианты разделителей, которые могут быть. В общем, это трабл?
Есть вариант - сравнить первые символы, потом вторые и т.д., но боюсь представить себе сколько будет работать скрипт!


Автор: GoodBoy 25.8.2004, 10:32
HalkaR, ну опять же...
(.+?) эта последовательность означает 1 и более повторов ЛЮБЫХ символов!!!!!!! Т. е. это соответствует как "аааааа", так и "дывшгардловпрппысоваы" и даже "96и 96ывпаан п9ы7нвапм ргывплрывп лфор"...

Автор: Secandr 25.8.2004, 10:41
s_a_s_h_a Тебе нужна система с "искуственым интелектом", тут простой выборкой не обойтись.

Автор: s_a_s_h_a 25.8.2004, 10:49
Secandr
Эх. Придется Пролог подключать smile.gif

Автор: HalkaR 25.8.2004, 11:02
GoodBoy , да я знаю. Поэтому я и не говорю, что это решение.

Автор: korob2001 25.8.2004, 12:26
Цитата

И почему бы не использовать модификатор g - что бы за раз делать все возможные замены?

s_a_s_h_a - писал что нужно удалять одинаковые последовательности только в начале строки. Потому я не использовал модификатор g
Цитата

А мочему [a-zA-ZА-Яа-я]? А если я напишу так [[[[[[[[[[[[[[[[[[[[

Я думал чел сам сможет добавить все необходимые символы.

Автор: Secandr 25.8.2004, 12:45
korob2001
я не внимательно пост прочёл, в итоге человеку совсем другое нужно

Автор: korob2001 25.8.2004, 12:56
Цитата

я не внимательно пост прочёл, в итоге человеку совсем другое нужно

А я твой не внимательно прочёл, ты внизу добавил. ;)

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