Модераторы: korob2001, ginnie
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Разбиение по символу, вне кавычек 
V
    Опции темы
JAPH
Дата 20.4.2007, 18:03 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 312
Регистрация: 8.1.2007
Где: Ленобласть

Репутация: 3
Всего: 23



Вопрос следующего плана. Имеется строка
some operation; one else operation; operation with ';'; and with ` ;`; with "`;'" also possible (':)');
Необходимо её разбить по точке с запятой, но только если она вне кавычек. Таким образом, нужно получить
Код

my @s = (
    'some operation',
    ' one else operation',
    " operation with ';'",
    ' and with ` ;`',
    q/ with "`;'" also possible (':)')/
);



--------------------
Что непонятно - спрашиваем smile
PM MAIL ICQ   Вверх
KSURi
Дата 20.4.2007, 20:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 887
Регистрация: 8.6.2006
Где: Russia

Репутация: 20
Всего: 27



Код

my $str=q{some operation; one else operation; operation with ';'; and with ` ;`; with "`;'" also possible (':)');};
print $_, "\n" foreach( split(/;[^']/, $str) );


Только почему-то получается, что and with ` ;`; захватывается не правильно =\
Код

-> some operation
-> one else operation
-> operation with ';'
-> and with `
->
-> with `;' also possible (':)');


Это сообщение отредактировал(а) KSURi - 20.4.2007, 20:26


--------------------
Died at Life.pl line 21
PM Jabber   Вверх
JAPH
Дата 20.4.2007, 20:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 312
Регистрация: 8.1.2007
Где: Ленобласть

Репутация: 3
Всего: 23



Потому что строка ;` соответствует шаблону ;[^']. Но даже если дополнить: ;[^'"`], это будет неправильно себя вести на строках вроде something ' containing ; in the center ' of the substring



--------------------
Что непонятно - спрашиваем smile
PM MAIL ICQ   Вверх
nitr
Дата 20.4.2007, 22:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 2543
Регистрация: 10.2.2006
Где: Россия :)

Репутация: 37
Всего: 84



JAPH, думаю все же сложный синтак. анализатор получится, на одних регулярках будет не просто сделать :(
хотя все же задачка решаема...
Код
#!perl
use strict; use warnings;

my $str = q{some operation; one else operation; operation with ';'; and with ` ;`; with "`;'" also possible (':)')};

my $begin = 0;
my $result;
my $tmp = '';

my $inner_token = '';
my $splitter = ';';
for (my $i = 0; $i <= length($str.$splitter); $i++) {
    my $s = substr($str.$splitter, $i, 1);
    if ($s =~ /['"`]/) {
        if ($begin == 1 and $inner_token eq $s) {
                $begin = 0;
                $inner_token = '';
        } else {
            $begin = 1;
            $inner_token = $s;
        }
    }
    if ($s eq $splitter and $begin == 0) {
        push @$result, $tmp;
        $tmp = '';
    } else {
        $tmp .= $s;
    }
}
print join("\n", @$result);

прошу оптимизацией самим заниматься ;) , но анализатор, имхо, "на лицо" smile
Если что, поясню код smile

Добавлено через 10 минут и 38 секунд
хех... вот тож самое smile но ближе к перл ;)
Код

...
foreach (split //, $str.$splitter) {
    if ($_ =~ /['"`]/) {
        if ($begin == 1 and $inner_token eq $_) {
                $begin = 0;
                $inner_token = '';
        } else {
            $begin = 1;
            $inner_token = $_;
        }
    }
    if ($_ eq $splitter and $begin == 0) {
        push @$result, $tmp;
        $tmp = '';
    } else {
        $tmp .= $_;
    }
}
...



--------------------
PM   Вверх
Nab
Дата 21.4.2007, 03:29 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 582
Регистрация: 25.3.2006
Где: Kiev

Репутация: 26
Всего: 37



У меня получилось вот такое:
Код

my $str = q{some operation; one else operation; operation with ';'; and with ` ;`; with "`;'" also possible (':)')};
print "--> $_\n" foreach( split(/([^;'"`]*(?:(?:'.*?'|".*?"|`.*?`)[^;]*)*);/, $str) );

Использовал альтернативы, потому как если заюзаем обратные ссылки, то они тоже попадут в вывод, что нам не нужно...
То есть вот такой код тоже работает, но он отдает и закавыченные места, и просто мусорит
Код

print "--> $_\n" foreach( split(/([^;'"`]*((['"`]).*?\3[^;]*)*);/, $str) );


Мой код тоже не идеален, он отдает пустое соответствие после каждого найденного :(, пока не знаю как избавиться...
То есть можно еще так проверить, чтобы получить только значимые результаты:
Код

my $str = q{some operation; one else operation; operation with ';'; and with ` ;`; with "`;'" also possible (':)')};
$_&&print "--> $_\n" foreach( split(/([^;'"`]*(?:(?:'.*?'|".*?"|`.*?`)[^;]*)*);/, $str) );




--------------------
 Чтобы правильно задать вопрос нужно знать больше половины ответа...
Perl Community 
FREESCO in Ukraine 
PM MAIL   Вверх
Nab
Дата 21.4.2007, 04:59 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 582
Регистрация: 25.3.2006
Где: Kiev

Репутация: 26
Всего: 37



Это мы делали через split, если делать поудобней, то вот так получаеться самый супер вариант:
Код

my $str = q{some operation; one else operation; operation with ';'; and with ` ;`; with "`;'" also possible (':)')};
print "--> $1\n" while( $str =~ /([^;'"`]*((['"`]).*?\3[^;]*)*);/g );





--------------------
 Чтобы правильно задать вопрос нужно знать больше половины ответа...
Perl Community 
FREESCO in Ukraine 
PM MAIL   Вверх
nitr
Дата 21.4.2007, 19:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 2543
Регистрация: 10.2.2006
Где: Россия :)

Репутация: 37
Всего: 84



Nab,  JAPH, привел пример:
something ' containing ; in the center ' of the substring, у меня твой не сработал :(

P.S.: но мне понравилось ;)

Это сообщение отредактировал(а) nitr - 21.4.2007, 19:28


--------------------
PM   Вверх
Nab
Дата 21.4.2007, 19:36 (ссылка) |  (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 582
Регистрация: 25.3.2006
Где: Kiev

Репутация: 26
Всего: 37



Цитата(nitr @  21.4.2007,  19:00 Найти цитируемый пост)
тем более JAPH, привел пример:something ' containing ; in the center ' of the substring, у меня твой не сработал :(

Конечно не сработает, потому как нет ни одного реального разделителя в виде ';'
нужно мой код исправить так:
Код

print "--> $1\n" while( $str =~ /([^;'"`]*((['"`]).*?\3[^;]*)*)/g );

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

Цитата(nitr @  21.4.2007,  19:00 Найти цитируемый пост)
Nab, все же мой код более рабочий, думаю сам понимаешь почему ;) 

Нет, nitr, не понимаю, хотя догадуюсь о чем ты.... 
Учитывая что эт я тебя познакомил с "конечными автоматами" smile (скромно. да?), то могу сказать по себе, что я их пытался применить везде где нужно было, и что печальнее, где не особенно нужно smile Они хороши в языках типа C, Delphi и т.д. где нет такой мощной поддержки регекспов. И хороши именно для синтаксического анализа... В перл же есть регулярки, которые в основе своей имеют теже конечные автоматы, просто они не видны пользователю.... И зачастую такие конструкции лучше реализовать на регекспах, чем строить конечный автомат... 
А вот применение конечных автоматов в более высокоуровневых конструкциях и организации машин состояний, очень даже полезная вещь, и ты это очень хорошо показал в топике по разбору внутренних таблиц в HTML. Так как он достаточно сложен чтоб разобрать его одной регуляркой, то там этот метод очень даже подходящий. 
Очень хорошо такая схема работает при паралельных работах, таких как POE, там даже методы определяющие интерфейс зовуться inline_state, object_state и т.д. хотя это немного не та машина состояний, которая идет отдельным компонентом...

Я эт говорю к тому, что не стоит пытаться применить новую технологию везде smile хорошего программиста отличает богатство опыта и арсенал оптимальных решений smile





--------------------
 Чтобы правильно задать вопрос нужно знать больше половины ответа...
Perl Community 
FREESCO in Ukraine 
PM MAIL   Вверх
nitr
Дата 21.4.2007, 19:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 2543
Регистрация: 10.2.2006
Где: Россия :)

Репутация: 37
Всего: 84



Цитата(Nab @  21.4.2007,  19:36 Найти цитируемый пост)
Учитывая что эт я тебя познакомил с "конечными автоматами"

только с данным определением smile
на Си была практика в написании синтак. анализатора ;)

По поводу регеспов соглашусь, поэтому и писал
Цитата(nitr @  21.4.2007,  19:00 Найти цитируемый пост)
но мне понравилось ;)

smile

А так в перл, на один вопрос "тыщу" ответов ;) хе хе. Мой без регеспов (то что там есть - не считается smile ), подходит нетолько для перл, согласись, тоже своего рода + ;)

А так твой код мне по душе smile (просто я времени не тратил на него), они мне полностью не дались, я это понял, когда тут появились такие замечательные участники как ты и amg smile офигенная коллекция регеспов ;)



--------------------
PM   Вверх
JAPH
Дата 21.4.2007, 20:40 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 312
Регистрация: 8.1.2007
Где: Ленобласть

Репутация: 3
Всего: 23



Спасибо, набросали возможных решений. Я думаю в том же направлении, что и Nab. Так как получающийся список будет обрабатываться в foreach, хотелось бы уместить это в одну регулярку. В общем, пока решением считаю доработанный вариант Nab`а с учётом возможности существования строк вида some string ' with escaped \' quotes ; and ' so on...;. Пустые поля (как между ;;) должны сохраняться, новых появляться не должно. Так что эта строка будет разбита на всё, кроме последней точки с запятой, и нечто пустое. Итак, вариант:

Код

use strict; use warnings;
while (<>) {
    print "-->$_\n" foreach
/
(?:(?<=^)|(?<=;))
((?:(?>[^;"'`]*)
    |
    (?>'(?:(?>[^'\\]*)|\\.)*')
    |
    (?>"(?:(?>[^"\\]*)|\\.)*")
    |
    (?>`(?:(?>[^`\\]*)|\\.)*`)
)*)
(?=;|$)
/xg;
    print "\n"
}

Проверяем, улучшаем, придираемся. smile

Ну и в качестве нарушения всех правил форума вопрос по форуму. Как вы делаете надпись "Добавлено через 2 минуты"?


--------------------
Что непонятно - спрашиваем smile
PM MAIL ICQ   Вверх
nitr
Дата 21.4.2007, 20:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 2543
Регистрация: 10.2.2006
Где: Россия :)

Репутация: 37
Всего: 84



JAPH, smile)
Цитата(JAPH @  21.4.2007,  20:40 Найти цитируемый пост)
Ну и в качестве нарушения всех правил форума вопрос по форуму. Как вы делаете надпись "Добавлено через 2 минуты"?

форум думаю хранит сессию..., потом смотрит, если моя мессага последняя, то добавляет тег перед моей новой мессагой
[mergetime]время в секундах с 1900 (вроде)[/mergetime]
вроде так smile




--------------------
PM   Вверх
Nab
Дата 21.4.2007, 22:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 582
Регистрация: 25.3.2006
Где: Kiev

Репутация: 26
Всего: 37



Блин, JAPH, без пол-литры не разобраться smile я в справочник полез, а то кое-чего никогда не встречал в реальном коде, и тем более не юзал smile

Поначалу я тоже хотел сделать на конструкциях предварительного и постусловий, но мне показалось удобней указать что должно быть, чем нахождение разделителя...

Я вот поглядел, и вроде как разобрал твой код... и вижу что тебе опятьже приходиться делать альтернативу для каждой кавычки, спецом чтоб не создавать найденных ссылок $1, $2 и т.д.

Я опять пошел путем универсальности и предлагаю такой вариант:
Код

use strict; use warnings;
# использую while 
while (<>) {
# и не $_, а беру необходимое соответствие
print "-->$1\n" while
/
(?:(?<=^)|(?<=;)) # Эта строка то, чего мне в split не хватало, не добавляет пустые строки в вывод ( как один из эффектов )
((?:(?>[^;"'`]*) # это чистый текст без всяких кавычек и точек с запятой.
    |                    # или
    (?>(['"`])([^\2\\]|\\.)*?\2)  # возможные строки в кавычках с игнорированием екранированых
                                               # кстати очень оригинальное решение, я его тоже себе возьму на заметку, 
                                               # как проходить экранированные символы
)*)
(?=;|$)
/xg;

print "\n";




--------------------
 Чтобы правильно задать вопрос нужно знать больше половины ответа...
Perl Community 
FREESCO in Ukraine 
PM MAIL   Вверх
Nab
Дата 22.4.2007, 09:19 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 582
Регистрация: 25.3.2006
Где: Kiev

Репутация: 26
Всего: 37



Кстати я вот подумал, что эт получаеться весьма мощная универсальная функция, разбиения строк по символу, с учетом закавыченных строк:
Код

sub split_s {
    my $s = shift;
    shift;
    my @result = ();
    push @result, $1 while /
        (?:(?<=^)|(?<=$s))
        (
            (?:
            (?>[^$s'"`]*)
         |
         (?>(['"`])([^\2\\]|\\.)*?\2)
            )*
        )
        (?=$s|$)
    /xg;

    return @result
}

my $str=q{some operation; one else operation; operation with ';'; and with ` ;`; with "`;'" also possible (':)');};
print "-->$_\n" foreach (split_s(';', $str));


Первым параметром принимает символ, а вторым строку, возвращает список полученных подстрок.
Символ должен быть один... в качестве разделителя больше одного не прокатит, ну или надо переписать и выделить разделитель как одну лексему....


--------------------
 Чтобы правильно задать вопрос нужно знать больше половины ответа...
Perl Community 
FREESCO in Ukraine 
PM MAIL   Вверх
JAPH
Дата 22.4.2007, 13:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 312
Регистрация: 8.1.2007
Где: Ленобласть

Репутация: 3
Всего: 23



Nab, один махонький недочёт в строке 3: 
Код
local $_ = shift;

А так здорово

Это сообщение отредактировал(а) JAPH - 22.4.2007, 20:47


--------------------
Что непонятно - спрашиваем smile
PM MAIL ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Perl"
korob2001
sharq
  • В этом разделе обсуждаются общие вопросы по языку Perl
  • Если ваш вопрос относится к системному программированию, задавайте его здесь
  • Если ваш вопрос относится к CGI программированию, задавайте его здесь
  • Интерпретатор Perl можно скачать здесь ActiveState, O'REILLY, The source for Perl
  • Справочное руководство "Установка perl-модулей", можно скачать здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, korob2001, sharq.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Perl: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0585 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.