sed, regexp (Выделение подстроки если её нет.)

На самом деле это единственный раздел про unix на этом форуме

Модераторы: /dev/random, Модераторы разделов

Аватара пользователя
Zeus
Сообщения: 694

sed, regexp

Сообщение Zeus »

Дана последовательность строк:

TS1 = "ts.channel0.station1.bit_1_2.o"; # Вкл $ X1-2
TS2 = "ts.channel0.station1.bit_2_5.no"; # Выкл $ X2-2
TS3 = "ts.channel1.station1.bit_1_3.o";# Перекл
TS_OK = "ts.channel0.station1.bit_1_1.o";


Таких строк много, но качественное отличие их друг от друга в том, что у некоторых может не быть "хвоста" после символа $, у некоторых всего хвоста после #.
Какие-то могут заканчиваться сразу после ; а у некоторых после этой точки с запятой могут быть пустые символы (пробелы, табы).

Нужно же на выходе получить:
0 1 1 2 title="X1-2">Вкл<
0 1 2 5 title="X2-2">Выкл<
1 1 1 3 title="">Перекл<
0 1 1 1 title="">1:1<

Т.е. выделить номера каналов, станций, адреса бит - с этим проблем нет.
А вот потом: если в строке есть #, то всё что идёт после неё (за исключением ведущих и завершающих пробелов) - оформить в > <
но дополнительно, если дальше идёт $, то всё что после него (за исключением ведущих и завершающих пробелов) - записать в title.
Это вроде заготовки для XML-тега.
Если же # в строке нет, то в тэг вставить адрес бита.

Вот собственно проблема - в разделении обработки строк где есть решётка (#) и где её нет.
Как ни бьюсь, всё получается: или все строки одинаково обрабатывает или одинаково не обрабатывает.

Хочу сделать примерно так:

Код: Выделить всё

sed "s/.*\".*channel\([[:digit:]]*\)\.station\([[:digit:]]*\)\.bit_\([[:digit:]]*\)_\([[:digit:]]*\)\.n{0,1}o\";[[:space:]]*[^#].*/\"ts.channel\1.station\2.bit_\3_\4.o\"; # \3:\4 $ Не описано/" |
sed "s/.*\".*channel\([[:digit:]]*\)\.station\([[:digit:]]*\)\.bit_\([[:digit:]]*\)_\([[:digit:]]*\)\.n[0,1]o\";[[:space:]]*#[[:space]]*\(.*\)[[:space:]]*$[[:space:]]*\(.*\)[[:space:]]*/\1 \2 \3 \4 title=\"\6\">\5</"

Т.е. первым выражением я в тех строках, где нет комментария (#...) - создаю его сам, а потом получившиеся более однотипные строки отправляю на второй sed, который формирует уже окончательный вывод.
Вот проблема - в первом sed. Никак не получается заставить нормально отработать конструкцию [^#]
Например, она не срабатывает если сразу после точки с запятой строка заканчивается.
И при этом же почему-то под обработку попадают строки, где комментарий - есть.

Два вопроса:
1. Что я не правильно написал в регэкспах в существующей концепции "2 sed"?
2. Может у меня сам принцип подхода к решению этой задачи неуклюжий и есть что-нибудь покрасивше?
Спасибо сказали:
Аватара пользователя
/dev/random
Администратор
Сообщения: 5404
ОС: Gentoo

Re: sed, regexp

Сообщение /dev/random »

Код: Выделить всё

#!/bin/sed -f

s/.*"ts\.channel\([0-9]*\)\.station\([0-9]*\)\.bit_\([0-9]*\)_\([0-9]*\)[^"]*";[[:space:]]*/\1 \2 \3 \4/
tx
:x
s/#[[:space:]]*\([^$]*\)/>\1</
ta
s/\([0-9]\+\) \([0-9]\+\)$/\0>\1:\2</
bb
:a
s/\(>.*\)\$[[:space:]]*\(.*\)/ title="\2"\1/
tc
:b
s/>/ title="">/
:c

Как-то так.
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: sed, regexp

Сообщение drBatty »

/dev/random писал(а):
19.01.2010 18:17
Как-то так.

вот спасибо! я тоже самое хотел сказать :)

Zeus писал(а):
19.01.2010 17:55
Два вопроса:
1. Что я не правильно написал в регэкспах в существующей концепции "2 sed"?
2. Может у меня сам принцип подхода к решению этой задачи неуклюжий и есть что-нибудь покрасивше?

1)см п2
2)в ваших скриптах наверное даже вы не разберётесь. запишите их пожалуйста в читаемом виде, скорее всего ошибка будет очевидна для вас.
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: sed, regexp

Сообщение Zeus »

/dev/random писал(а):
19.01.2010 18:17

Код: Выделить всё

#!/bin/sed -f

s/.*"ts\.channel\([0-9]*\)\.station\([0-9]*\)\.bit_\([0-9]*\)_\([0-9]*\)[^"]*";[[:space:]]*/\1 \2 \3 \4/
tx
:x
s/#[[:space:]]*\([^$]*\)/>\1</
ta
s/\([0-9]\+\) \([0-9]\+\)$/\0>\1:\2</
bb
:a
s/\(>.*\)\$[[:space:]]*\(.*\)/ title="\2"\1/
tc
:b
s/>/ title="">/
:c

Как-то так.

Хм. Прикольно :)
Вроде работает, хотя пока и непонятно как. Потом разберусь.
Спасибо.
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: sed, regexp

Сообщение drBatty »

Zeus писал(а):
20.01.2010 11:32
хотя пока и непонятно как

как вы в первом посте написали, так и работает, дословно: "если в строке есть ... меняем его на ... (команда s) и переходим к метке :a (команда ta)"
я-бы ещё отступов добавил, и некоторые условия проверял бы так

Код: Выделить всё

/если это есть в строке/ {
#то выполняется этот код
}
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
/dev/random
Администратор
Сообщения: 5404
ОС: Gentoo

Re: sed, regexp

Сообщение /dev/random »

Да, и, если непонятно, код
tx
:x
- это просто сброс условия перехода. Чтобы идущий перед этим s/// не повлиял на дальнейшие проверки.
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: sed, regexp

Сообщение drBatty »

у меня только 2 замечания:
1) всё было-бы ещё проще, если в начале заменить -f на -rf, тогда-бы не пришлось экранировать многие символы.
2) вместо [[:space:]] можно писать \s

ещё метка :c лишняя, но это уже мне не к чему придраться :)
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали: