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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как обрезать строку до не разбивая слов, до определенной длинны. 
:(
    Опции темы
sir_nuf_nuf
Дата 5.10.2009, 14:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

Репутация: 1
Всего: 31



Товарищи, хочу предложить вам жизненную задачу на регулярки:

Задача проста:
Нужно обрезать строку до заданной длинны, стараясь по возможности не разбивать слова.
В конце строки нужно дописать троеточие (типа "есть продолжение")

Требование:
1) результат, вместе троеточием должен быть не длиннее указанной числа символов 
2) не разбивать слова, т.е. обрезать предложение нужно между словю
3) между последним словом и троеточием не должно быть пробелов.


Я пока решил эту задачу на if - решил не извращаться с регуляркой.

Кто сможет написать regexp ?



--------------------
user posted image
user posted image
PM MAIL Jabber   Вверх
gcc
Дата 5.10.2009, 14:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Агент алкомафии
****


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

Репутация: нет
Всего: 17



а что должно получиться?

вот например я делал обрезать длинные слова и длинные строки...

Код


sub stat_cut_big : Private {
    my ( $self, $c, $text_cut ) = @_;
    $text_cut ||= '';

    return length($text_cut) > 30 ? substr( $text_cut, 0, 30 ) : $text_cut;

}

sub stat_cut : Private {
    my ( $self, $c, $text_cut ) = @_;
    my $cut_hash;
    $text_cut ||= '';
        my $h;
    my @len = split( / /, $text_cut, 8 );
    my $big;
    foreach (@len) {
        if ( length($_) > 16 ) {
            $big = 1;
            # binmode(STDOUT,":utf8");
             $_ = Encode::decode('utf8', $_);

#use MIME::Base64;
# use Encode qw(_utf8_off);
#use utf8;
# $str = 'Текст в utf-8';
#_utf8_off($_);
#$_ = encode_base64($_, '');            
            
            $_ = substr $_, 0, 16;
            $_ .= '.. ';
          $_ = Encode::encode('utf8', $_ );

        }
    }

    return $big ? join( ' ', @len ) : $text_cut;

}


так вот вызвать:
Код

    $c->stash->{new_section_id1} = $loop_data->[0]->[0];
    $c->stash->{new_section_all1} =
      $c->forward( 'stat_cut_big', [ $loop_data->[0]->[1] ] );
    $c->stash->{new_section_cut1} =
      $c->forward( 'stat_cut', [ $loop_data->[0]->[1] ] );


Это сообщение отредактировал(а) gcc - 5.10.2009, 14:49
PM WWW ICQ Skype GTalk Jabber   Вверх
shamber
Дата 5.10.2009, 15:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1422
Регистрация: 5.9.2006
Где: Россия

Репутация: нет
Всего: 18



gcc, это регулярка?

Это сообщение отредактировал(а) shamber - 5.10.2009, 15:22
PM MAIL Jabber   Вверх
gcc
Дата 5.10.2009, 15:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Агент алкомафии
****


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

Репутация: нет
Всего: 17



shamber, точно нет... 
PM WWW ICQ Skype GTalk Jabber   Вверх
sir_nuf_nuf
Дата 5.10.2009, 16:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

Репутация: 1
Всего: 31



должно получиться примерно следующее:
Код

print wordcate("big bang theory",  13);
#bing bang...




--------------------
user posted image
user posted image
PM MAIL Jabber   Вверх
KSURi
Дата 5.10.2009, 19:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Код

#!/usr/bin/evn perl

use Modern::Perl;

my @data = (
    'Hello World!',
    'This is very-very-very-very-very long string. Really long.',
    'This one is short.',
);
s{^.{0,13}\K\s.*$}{...} for @data;
say for @data


Легко можно сделать жадный вариант (нарушает п. 1, но на всякий случай):
Код

s{^.{13,}\K\s.*$}{...} for @data;


Это сообщение отредактировал(а) KSURi - 5.10.2009, 19:27


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


Опытный
**


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

Репутация: 1
Всего: 31



KSURi, не работает.
видно на 'This is very-very-very-very-very long string. Really long.'


--------------------
user posted image
user posted image
PM MAIL Jabber   Вверх
amg
Дата 6.10.2009, 07:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1145
Регистрация: 3.8.2006
Где: Новосибирск

Репутация: нет
Всего: 50



Вот что я придумал (правда, не только регулярка, плюс к ней еще pos и пробелы в начале строки нужно удалять)
Код
my @data = ('
Hello!','
Hello World!','
This is very-very-very-very-very long string. Really long.','
This one is short.','
Very-very-very-very-very_long_word',
);

foreach (@data) {
  s/^\s+//;
  pos = 13-3;
  s/(?:\s+\S*|)\G.{4,}/.../;
  print length,": '$_'\n";
}


PM MAIL   Вверх
gcc
Дата 6.10.2009, 07:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Агент алкомафии
****


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

Репутация: нет
Всего: 17



а почему нельзя написать без регулярки? регулярка быстрее будет?

просто пока это все понапридумывать - так очень много времени тратиться на это
PM WWW ICQ Skype GTalk Jabber   Вверх
KSURi
Дата 6.10.2009, 08:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(sir_nuf_nuf @  5.10.2009,  23:18 Найти цитируемый пост)
KSURi, не работает.
видно на 'This is very-very-very-very-very long string. Really long.' 

Почему? У меня выводит "This is...".

UPD:
Нашел пару недочетов, поправил.  Вроде не нарушает ниодного пункта.
Код

my $total_max = 13;
my $ending = '...';
my $meaning_max = $total_max - length $ending;
length > $total_max and s/^.{0,$meaning_max}\K[\s-].*$/$ending/ for @data;


Это сообщение отредактировал(а) KSURi - 6.10.2009, 08:30


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


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1495
Регистрация: 31.10.2004

Репутация: нет
Всего: 40



perl -le 'print $ARGV[0] =~ m#^(.{15,24}\S)\b# ? "$1..." : $ARGV[0]'
PM MAIL ICQ   Вверх
Logo
Дата 8.10.2009, 09:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

Репутация: 5
Всего: 10



А что считать словом? Машинное слово? Тогда:
Код

$_ = 'This is very-very-very-very-very long string. Really long.';
$maxn = 15;
$n = $maxn - 3;
m/^.{0,$n}\b(?=(?:\W|$))/;
print "$&...";


Цитата

а почему нельзя написать без регулярки? регулярка быстрее будет?

просто пока это все понапридумывать - так очень много времени тратиться на это 


Что бы развить моск. При тренировке регулярками как правило наоборот, время меньше тратится.

Это сообщение отредактировал(а) Logo - 8.10.2009, 13:11
PM MAIL   Вверх
amg
Дата 8.10.2009, 10:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1145
Регистрация: 3.8.2006
Где: Новосибирск

Репутация: нет
Всего: 50



Logo, а если
$_ = 'This_is_very_very_very_very_very_long_word.'; smile
PM MAIL   Вверх
Logo
Дата 8.10.2009, 13:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

Репутация: 5
Всего: 10



amg
Можно добавить
Код

m/^.{0,$n}(?:\b(?=(?:\W|$))|^)/;


PM MAIL   Вверх
amg
Дата 8.10.2009, 15:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1145
Регистрация: 3.8.2006
Где: Новосибирск

Репутация: нет
Всего: 50



Цитата(Logo @  8.10.2009,  13:10 Найти цитируемый пост)
Можно добавить...
 Не помогает. Все равно длинное слово вырезается полностью. (хотя в условии, строго говоря, не сказано, что такого быть не должно, но исходя из здравого смысла, логично было бы оставлять часть слова).

Кроме того, пусть, например, строка содержит ровно $maxn символов. Твоё решение такую строку обрежет. А логично было бы оставить ее как есть -- она же помещается.

И к совсем коротким словам добавит ... Еще одну проверку? (В условии то сказано "только регуляркой". Хотя этого никто пока не смог соблюсти).

PM MAIL   Вверх
Logo
Дата 8.10.2009, 16:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

Репутация: 5
Всего: 10



Цитата

Не помогает. Все равно длинное слово вырезается полностью. (хотя в условии, строго говоря, не сказано, что такого быть не должно, но исходя из здравого смысла, логично было бы оставлять часть слова).

Ну да, я и поправил только некорректное не обявленное значение переменной.

Цитата

Кроме того, пусть, например, строка содержит ровно $maxn символов. Твоё решение такую строку обрежет. А логично было бы оставить ее как есть -- она же помещается.

Верно, и если она меньше $maxn... Сама регуляка только делает "результат, вместе троеточием должен быть не длиннее указанной числа символов". Можно поставить if на длинну строки в коде, хотя и регуляркой тоже можно
Код

$maxn = 8;
$n = $maxn - 3;
print "$&..." if m/^(?=.{$maxn}.+$).{0,$n}\b(?=(?:\W|$))/s;


PM MAIL   Вверх
Logo
Дата 10.10.2009, 13:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

Репутация: 5
Всего: 10



Одной регуляркой, и с учетом пожеланий amg. Хотя это уже изврат, наверное smile. Разобьет, если на границе слово длинной  7 и более символов. Словом считается [a-z]([a-zа-яё'-]*[a-zа-яё])? ,  т.е. don't и Римский-Корсаков проходят.
Код

$_ ='This is very-very-very-very-very long string. Really long.';
print strip($_, 20);

sub strip {
  my $maxn = pop;
  my $n = $maxn-3;
  return $_[0] =~ m{
  ^.*?
  (?=.{$maxn}.)
  (?:
      ((?=\s* ((?<=.{$n}))? [a-zа-яё] (?:[a-zа-яё'-]){5,} [a-zа-яё] ((?<=..{$n}))) (?(3)(?(2)(?!)|)|(?!)) )|
      (?=\s*[a-zа-яё](?:[a-zа-яё'-]*[a-zа-яё])?(?<=..{$n}))|
      (?<=.{$n})
  )
  (?(1)\s*.*?(?<=.{$n}))
  }xs ? "${^MATCH}..." : $_[0];
}




Цитата

Не помогает. Все равно длинное слово вырезается полностью. (хотя в условии, строго говоря, не сказано, что такого быть не должно, но исходя из здравого смысла, логично было бы оставлять часть слова).

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

Цитата

И к совсем коротким словам добавит ... Еще одну проверку? (В условии то сказано "только регуляркой". Хотя этого никто пока не смог соблюсти).

Про это непонял

Это сообщение отредактировал(а) Logo - 10.10.2009, 13:54
PM MAIL   Вверх
ad280379
Дата 2.12.2009, 08:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата(arto @ 6.10.2009,  14:42)
perl -le 'print $ARGV[0] =~ m#^(.{15,24}\S)\b# ? "$1..." : $ARGV[0]'

помоему это есть наиболее правильное решение на основе регулярных выражений.
единственно не понимаю (т.е. считаю что не правильно)  указание \S (вместо \s) и не понятно зачем нижняя граница {15,24}

я переписал это так (в данном решении N количество выводимых символов)
формат - prg_name.pl N "Hello and welcome dears"
результат при N=10 будет "Hello and ..."

---code---
$text = $ARGV[1];
$ltext = length($ARGV[1]);
print "[$ltext],[$ARGV[0]],$text" if($text=~m/^(.{0,$ARGV[0]}\s*)\b/ ? ($text="$1...") : ($text.="..."));
---code end---


конструктивная критика приветствуется  smile 

PM MAIL   Вверх
Logo
Дата 12.12.2009, 22:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

Репутация: 5
Всего: 10



Цитата

помоему это есть наиболее правильное решение на основе регулярных выражений.

Очень коротко и аргументировано smile 
PM MAIL   Вверх
ad280379
Дата 12.12.2009, 23:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата(Logo @ 12.12.2009,  22:09)
Цитата

помоему это есть наиболее правильное решение на основе регулярных выражений.

Очень коротко и аргументировано smile

ну... вы же Бывалый... вообще должны с двух слов понимать
PM MAIL   Вверх
amg
Дата 14.12.2009, 12:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1145
Регистрация: 3.8.2006
Где: Новосибирск

Репутация: нет
Всего: 50



Господа!
По моему, мы несколько неправильно понимаем задачу. Насколько я себе представляю, она состоит не в том, чтобы написать код, делающий сформулированные в 1-м посте вещи, и даже не в том, чтобы этот код был самым коротким/изящным, а в том, чтобы сделать это только ругуляркой. И такая постановка задачи, IMHO, так пока и не решенной, оправдана. Во-первых, тогда решение будет почти прямо переносимо на любой ЯП, где есть PCRE, во-вторых, существуют программы a'la grep, которым на вход нужно давать регулярное выражение и ничего кроме него.
PM MAIL   Вверх
Logo
Дата 14.12.2009, 23:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

Репутация: 5
Всего: 10



Цитата

И такая постановка задачи, IMHO, так пока и не решенной

А как же мой код smile 
PM MAIL   Вверх
amg
Дата 16.12.2009, 11:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1145
Регистрация: 3.8.2006
Где: Новосибирск

Репутация: нет
Всего: 50



Цитата(Logo @  14.12.2009,  23:09 Найти цитируемый пост)
А как же мой код
И в самом деле. А я твой код как-то пропустил, т.к. после беглого взгляда на него он у меня не ассоциировался с регулярным выражением (они обычно не так выглядят) smile .

PM MAIL   Вверх
ad280379
Дата 16.12.2009, 20:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата(Logo @ 14.12.2009,  23:09)
Цитата

И такая постановка задачи, IMHO, так пока и не решенной

А как же мой код smile

А как же мой код  smile я старался  smile 
 smile  smile 
PM MAIL   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Perl: Регулярные выражения | Следующая тема »


 




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


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

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