Forum Webscript.Ru

Программирование => Perl => Тема начата: w01k от 03 Июня 2008, 13:35:23

Название: помогите придумать регулярное выражение
Отправлено: w01k от 03 Июня 2008, 13:35:23
задача следующая: разделить разряды ЦЕЛОГО числа запятыми слева направо. всё должно быть оформлено в виде s/regexp/.../g. при этом числа могут быть разделены точками

у меня получается только так:
$src =~s/((?:\\D+\\.)|(?:\\s\\d*?))(\\d\\d\\d)(?=(\\d+\\.\\D+)|(\\d+\\s))/\\1\\2,/g;

при этом
исходная строка: ...15785456451  556 88 4   fghd454444    4210101.98752 7895.3545135 984785848 156518..4856..
результат: ...157,85456451  556 88 4   fghd454444    4210101.98752 7895.3545135 984,785848 156,518..485,6..

либо так:
$src =~s/(?
исходная строка: ...15785  556 88 4   fghd454444    4210101.98752 7895.3545135 984785848 156518..4856..
результат: ...157,85  556 88 4   fghd454,444    4210101.9875,2 7895.3545,135 984,785,848 156,518..485,6..
Название: помогите придумать регулярное выражение
Отправлено: w01k от 03 Июня 2008, 18:44:48
строчка
$src =~s/(\\d\\d\\d)||(\\W\\d+\\.\\d+)||([A-Za-z]+\\d+\\W)/\\1/g;
выводит всё, кроме тех чисел и переменных, которые не нуждаются в разделении на разряды.
...15785  556 88 4   fghd454444 4578/456/5/46445:45454:5:45:564556   4210101.98752 7895.3545135 984785848 156518..4856..Testing... OK! It works

...15785  556 88 4   4578/456/5/46445:45454:5:45:564556   984785848 156518..4856..Testing... OK! It works
 как этим воспользоваться - не понимаю(((


можно ли каким-нибудь образом совместить эти строки в одну?
$src =~s/[A-Za-z]+\\d+//g;
$src =~s/\\d+\\.\\d+//g;
$src =~s/(\\d\\d\\d)(?=\\d)/\\1,/g;
они делают, что требуется, правда, удаляют всё, не подходящее под шаблон
исх. строка: ...15785  556 88 4   fghd454444 4578/456/5/46445:45454:5:45:564556   4210101.98752 7895.3545135 984785848 156518..4856..Testing... OK! It works
результат: ...157,85  556 88 4    457,8/456/5/464,45:454,54:5:45:564,556     984,785,848 156,518..485,6..Testing... OK! It works


ещё вопрос, можно писать так:
perl -pe -e \'s///\' -e \'s///\' filename
Название: помогите придумать регулярное выражение
Отправлено: ravshaniy от 04 Июня 2008, 10:32:30
Цитировать
w01k:
ещё вопрос, можно писать так:
perl -pe -e \'s///\' -e \'s///\' filename


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


Цитировать
w01k:
можно ли каким-нибудь образом совместить эти строки в одну?

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

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

my $str = \'15785 556 88 4 fghd454444 4578/456/5/46445:45454:5:45:564556 4210101.98752 7895.3545135 984785848 156518..4856..\';
$str.=\' \';
@str=$str=~m/(.*?)\\s/g;
@str=grep{/^(\\d+)$/} @str;
print $_,", " foreach(@str);
Название: помогите придумать регулярное выражение
Отправлено: w01k от 04 Июня 2008, 17:25:55
в том то и дело, что задача состоит в том, чтобы решение представляло собой одну строчку. причём запускаемую через командную строку вида:
perl [-p -e -i] \'s/regexp/.../g\'
вот(((
Название: помогите придумать регулярное выражение
Отправлено: w01k от 04 Июня 2008, 17:52:12
нужно не просто вывести все целые числа, разделяя их запятой, а модифицировать исходный текст файла/строки так, чтобы в целых числах разряды разделялись запятой. например:
454153 7842 45 456 7845.12 789,456:45:1234562 ах1000
454,153 784,2 45 456 7845.12 789,456:45:123,456,2 ах1000
Название: помогите придумать регулярное выражение
Отправлено: ravshaniy от 04 Июня 2008, 18:03:11
хм забавно
а такая вещь спасет вас?
s/(\\d{3})(\\d)/\\1,\\2/g
Название: помогите придумать регулярное выражение
Отправлено: ravshaniy от 04 Июня 2008, 18:20:10
по всей видимости нет, вы можете привести точный листинг задачи?
Название: помогите придумать регулярное выражение
Отправлено: w01k от 04 Июня 2008, 18:43:53
собственно говоря, всё уже написал:
все целые числа разделить запятыми на разряды слева направо. ответ представить в виде perl [-p -e -i] \'s/regexp/.../g\'
Название: помогите придумать регулярное выражение
Отправлено: ravshaniy от 05 Июня 2008, 17:21:44
ну собственно говоря. что вы хотите?
провести операции с файлом или со строкой и для вас не важно каким способом главное чтобы целые числа разделить запятыми на разряды слева направо

или
вам нужно регулярное выражение которое бы сделало из исходной строки
454153 7842 45 456 7845.12 789,456:45:1234562 ах1000
результирующую
454,153 784,2 45 456 7845.12 789,456:45:123,456,2 ах1000

как бы если разделить сложную задачу на две простые станет все проще.

и подумать над второй задачей есть смысл в том плане что интересно, если вы не будите бесконечно прибавлять к ней вызов перла, давайте обсудим ее. если весь интерес именно в нахождении регулярного выражения?
Название: помогите придумать регулярное выражение
Отправлено: ravshaniy от 05 Июня 2008, 17:23:55
я к тому что не добавляйте лишних слов лишних сущностей. давайте для начала определим уровень абстракции. и проставим правильный акцент в задаче
Название: помогите придумать регулярное выражение
Отправлено: ravshaniy от 05 Июня 2008, 17:38:23
И в нахождении регулярного выражения у нас возникает проблема с первым и последним набором символов/*словом*/ в строке /* в предложении*/. Исходное выражение приходится модернизировать чтобы правильно найти слова в предложении придется к исходному выражению прибавить по пробелу с начала и с конца.

тогда можно будет написать регулярное выражение

s/[\\s|,|:]((\\d{3})(\\d+))[\\s|,|:]/\\2,\\3/g

мне кажется если в исходной строке вы сделаете выше описанные изменения то данное регулярное выражение и замена удовлетворят вашим условиям задачи
Название: помогите придумать регулярное выражение
Отправлено: w01k от 05 Июня 2008, 23:53:15
Цитировать
ну собственно говоря. что вы хотите?
провести операции с файлом или со строкой и для вас не важно каким способом главное чтобы целые числа разделить запятыми на разряды слева направо

или
вам нужно регулярное выражение которое бы сделало из исходной строки
454153 7842 45 456 7845.12 789,456:45:1234562 ах1000
результирующую
454,153 784,2 45 456 7845.12 789,456:45:123,456,2 ах1000

строка - просто частность, пример различных комбинаций цифр.
Цитировать
s/[\\s|,|:]((\\d{3})(\\d+))[\\s|,|:]/\\2,\\3/g

эт всё не то.   во-первых, результирующая строка будет "съедать" пробелы/какие-либо разделители. во-вторых, отделится только первый разряд
 123456789
 123,456789 (а надо 123,456,789)

я, вроде, придумал регулярное выражение (парился дня 3, при том, что это было задание на 40 минут...)

s/([^\\w\\.]|\\.\\.|\\G)(\\d{3})(?=(\\d+\\.\\D+)|(\\d+\\s))/\\1\\2,/g
Название: помогите придумать регулярное выражение
Отправлено: ravshaniy от 06 Июня 2008, 11:27:55
отличное регулярное выражение. объясните только необходимость
(\\d+\\.\\D+)| - я думаю что
s/([^\\w\\.]|\\.\\.|\\G)(\\d{3})(?=(\\d+\\s))/\\1\\2,/g
вполне хватет
Название: помогите придумать регулярное выражение
Отправлено: ravshaniy от 06 Июня 2008, 12:07:43
и все таки это регулярное выражение не справилось с таким выражением
789345345345345456:45:1234562

предлагаю все же - гну свою линию:
s/(\\s|,|:|\\G)(\\d{3})(?=\\d+(\\s|,|:|\\G))/$1$2,/g;
Название: помогите придумать регулярное выражение
Отправлено: w01k от 06 Июня 2008, 12:54:50
спасибо за придуманный пример.
Цитировать
объясните только необходимость
(\\d+\\.\\D+)|

это нужно для того, чтобы числа вида 1234.12323 не обрабатывались, т.к. они не целые.
Цитировать
предлагаю все же - гну свою линию:
s/(\\s|,|:|\\G)(\\d{3})(?=\\d+(\\s|,|:|\\G))/$1$2,/g;

кроме \\s, , и : цифры могут быть разделены кучей других символов - придётся все перечислить. к тому же бессмыслено ставить знак конца предыдущего совпадения \'\\G\' до и после шаблона.
вот выражение, которое справилось со строкой

789345345345345456:45:1234562

s/([^\\w\\.]|\\.\\.|\\G)(\\d{3})(?=(\\d+\\.\\D+)|(\\d+[^\\w\\.])|(\\d+\\Z))/\\1\\2,/g

789,345,345,345,345,456:45:123,456,2
Название: помогите придумать регулярное выражение
Отправлено: ravshaniy от 06 Июня 2008, 21:47:18
вынужден не согласится
(\\d+\\.\\D+)| - излишне, так как следующее выражение (\\d+[^\\w\\.]) также справится с задачей не обрабатывать числа типа 1234.12323 если не верите попробуйте убрать и результат не изменится.
на счет \\G - это вместо \\A и \\Z. по той простой причине что //g и в нем большой смысл, я его использую вместо добавочных пробелов, которые я по незнанию добавлял к исходной строке. спасибо за вопрос. отвечая на него я узнал еще чуть больше. *приобрел новый опыт, может быть через неделю я пойму зачем он нужен*(из фильма пять препятствий, или совершенный человек)
Название: помогите придумать регулярное выражение
Отправлено: w01k от 07 Июня 2008, 08:53:41
Цитировать
(\\d+\\.\\D+)| - излишне, так как следующее выражение (\\d+[^\\w\\.]) также справится с задачей не обрабатывать числа типа 1234.12323 если не верите попробуйте убрать и результат не изменится.

не излишне, потому что 789645..4566 это два целых числа, а без (\\d+\\.\\D+)| они не будут обрабатываться