sed и конец строки (Не обрабатывается '$', почему?)

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

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

Аватара пользователя
gluk47
Сообщения: 297
Статус: Любитель гвоздей и микроскопов
ОС: Kubuntu 17.10

sed и конец строки

Сообщение gluk47 »

Доброго ${daytime}.

Я хочу заменить в тексте в нужных местах все '-' на '—', для чего написал команду:

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

sed 's/\(^\| \)-\($\| )/\1—\2/g' <src >dest

Но дефисы, прижатые к концам строк, не обрабатываются, что я делаю не так?

Ссылку в подписи drBatty я читал) Там написано, что '$' означает «конец буфера sed». А раз /g означает “globally”, я подумал, что конец буфера приходится на конец файла, стоит убрать /g и посмотреть, что будет со строкой вида ^[^-]* -$, то есть первый дефис в строке встречается после какого-то слова и стоит как раз перед концом строки. Опять не работает…
[gluk47@gluk47-desktop ~]$ ензу куищще
куищще is aliased to `reboot'
Спасибо сказали:
Аватара пользователя
diesel
Бывший модератор
Сообщения: 5989
ОС: OS X, openSuSE, ROSA, Debian

Re: sed и конец строки

Сообщение diesel »

gluk47 писал(а):
21.01.2010 00:32
Доброго ${daytime}.

Я хочу заменить в тексте в нужных местах все '-' на '—', для чего написал команду:

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

Re: sed и конец строки

Сообщение drBatty »

gluk47 писал(а):
21.01.2010 00:32
Я хочу заменить в тексте в нужных местах все '-' на '—', для чего написал команду:
Код
sed 's/\(^\| \)-\($\| )/\1—\2/g' <src >dest

Зачем так сложно?

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

sed 's/ - / — /g; s/^- /— /; s/ -$/ —/'

насколько я помню, конструкция вида (^|X) опасна - некоторые версии sed могут это не понять.
gluk47 писал(а):
21.01.2010 00:32
1)Там написано, что '$' означает «конец буфера sed».
2)А раз /g означает “globally”, я подумал, что конец буфера приходится на конец файла

1)да
2)там так-же написано, что sed обрабатывает текст построчно. потому /g означает - "произвести все замены в строке", а $ точно так-же означает "конец строки".
Конец текста обозначается в RE как \', однако только в мультистрочном режиме, и только если загрузить весь текст в буфер (что не слишком просто, т.к. для этого ещё и извернутся надо: N в цикле выполнить). не забивайте голову, используйте просты выражения. :)
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
gluk47
Сообщения: 297
Статус: Любитель гвоздей и микроскопов
ОС: Kubuntu 17.10

Re: sed и конец строки

Сообщение gluk47 »

diesel писал(а):
21.01.2010 00:34
опишите словесно в каких именно местах...

Тире должно ставиться между словами вместо дефиса там (и только там), где вокруг дефиса с каждой стороны есть хотя бы один пробел или начало/конец строки. Именно это я и написал sed'у в команде.
Не работает тут, например:

Код:

$ cat src testtext - ohno $


drBatty писал(а):
21.01.2010 01:29
gluk47 писал(а):
21.01.2010 00:32
sed 's/\(^\| \)-\($\| )/\1—\2/g' <src >dest

Зачем так сложно?

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

sed 's/ - / — /g; s/^- /— /; s/ -$/ —/'

насколько я помню, конструкция вида (^|X) опасна - некоторые версии sed могут это не понять.

Мой sed понимает :) Поскольку решение лично для меня, то пусть пока останется.
А почему нет?.. конструкция же построена по правилам regexp, нет?
В данном случае можно перечислить все альтернативы, но даже это как-то непонятно: регулярные выражения же как раз придуманы для описания шаблонов, а sed их поддерживает как раз…
Потом я хотел кавычки поменять, например. Вставить типографские закрывающие командой вида:

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

sed s/\([^ ]\)"\($\|[,;:. -]\)/\1»\2/g
.
Здесь уже весьма много альтернатив в правой части, не перечислять же их все.

В общем-то в данном случае помогает простановка звёздочки после квадратных скобок в правой части. В силу специфики текста (литературное произведение) символы в квадратных скобках всё равно встречаются не больше одного подряд, а если ноль — то как раз конец строки. Но выглядит как хак и даже тут не всегда верно)
[gluk47@gluk47-desktop ~]$ ензу куищще
куищще is aliased to `reboot'
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: sed и конец строки

Сообщение drBatty »

gluk47 писал(а):
21.01.2010 02:13
Мой sed понимает smile.gif Поскольку решение лично для меня, то пусть пока останется.
А почему нет?.. конструкция же построена по правилам regexp, нет?

1) сейчас понимает, завтра не поймёт. или на другом компьютере не поймёт, или после обновления, или...
2) а я не перечисляю ВСЕ альтернативы, и вам не предлагаю: я предлагаю просто обработать отдельно ОСОБЫЕ случаи - начало и конец строки.
ну да ладно, это всё демагогия, если позволите, я буду заменять - на +, и набирать удобнее и видно лучше

Shell

$ cat >test.txt - jfjsks - jjdks - - hfjdh-d -- - jdks - djjd - dd - - jdjd -


Shell

$ sed -r 's/(^| )-( |$)/\1+\2/g' test.txt + jfjsks + jjdks + + hfjdh-d -- + jdks + djjd + dd + + jdjd +


В чём проблема?

с дефисом тоже работает.

Почему не работает у вас? Наверное одно из трёх:
1) ваша sed всё-таки непонимает такие конструкции.
2) у вас не настроен режим UTF-8 (а тире оттуда)
3) у вас строки завершаются не \n как положено, а скажем \r\n как в маздае, либо \r как в маке, либо строка последняя и вы забыли перевод строки.
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
gluk47
Сообщения: 297
Статус: Любитель гвоздей и микроскопов
ОС: Kubuntu 17.10

Re: sed и конец строки

Сообщение gluk47 »

Действительно глупость написал, все альтернативы не надо разворачивать. И всё же…)

1. sed принципиально не поддерживает маски вида (^| ) ? Что именно тут не подходит по стандарт regexp?.. Или я просто не дочитал до этого места в вашей же ссылке?
2. Действительно, всё так и оказалось. Его нужно настраивать в параметрах sed или где-то в параметрах терминала/баша/локали?..
3. Строки юниксовые, \n) И кодировка (которая utf8 как раз). '$' — это не якорь конца строки разве? То есть если там не только конец строки, но сразу и конец файла, то $ не подходит?
[gluk47@gluk47-desktop ~]$ ензу куищще
куищще is aliased to `reboot'
Спасибо сказали:
Аватара пользователя
/dev/random
Администратор
Сообщения: 5398
ОС: Gentoo

Re: sed и конец строки

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

gluk47 писал(а):
21.01.2010 14:21
'$' — это не якорь конца строки разве?

Якорь, якорь. Только POSIX говорит, что если $ не является последним символом регулярного выражения, то результат _не определён_. То же с ^ : он должен быть первым символом регулярного выражения. В противном случае sed по своему усмотрению имеет право (но не обязан) считать его просто символом, не имеющим специального значения.
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: sed и конец строки

Сообщение drBatty »

gluk47 писал(а):
21.01.2010 14:21
2. Действительно, всё так и оказалось. Его нужно настраивать в параметрах sed или где-то в параметрах терминала/баша/локали?..

Another problem is that `[a-z]' tries to use collation symbols.
This only happens if you are on the GNU system, using GNU libc's
regular expression matcher instead of compiling the one supplied
with GNU sed. In a Danish locale, for example, the regular
expression `^[a-z]$' matches the string `aa', because this is a
single collating symbol that comes after `a' and before `b'; `ll'
behaves similarly in Spanish locales, or `ij' in Dutch locales.

To work around these problems, which may cause bugs in shell
scripts, set the `LC_COLLATE' and `LC_CTYPE' environment variables
to `C'.

помогает не только от того, от чего написано...
gluk47 писал(а):
21.01.2010 14:21
$' — это не якорь конца строки разве? То есть если там не только конец строки, но сразу и конец файла, то $ не подходит?

нет.
строки должны заканчиваться \n
иначе это не строки.

/dev/random писал(а):
21.01.2010 18:19
Только POSIX говорит, что если $ не является последним символом регулярного выражения, то результат _не определён_. То же с ^ : он должен быть первым символом регулярного выражения. В противном случае sed по своему усмотрению имеет право (но не обязан) считать его просто символом, не имеющим специального значения.

не. ИМХО это касается только выражений вроде X^Y
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
diesel
Бывший модератор
Сообщения: 5989
ОС: OS X, openSuSE, ROSA, Debian

Re: sed и конец строки

Сообщение diesel »

drBatty писал(а):
21.01.2010 19:24
/dev/random писал(а):
21.01.2010 18:19
Только POSIX говорит, что если $ не является последним символом регулярного выражения, то результат _не определён_. То же с ^ : он должен быть первым символом регулярного выражения. В противном случае sed по своему усмотрению имеет право (но не обязан) считать его просто символом, не имеющим специального значения.

не. ИМХО это касается только выражений вроде X^Y

нет.
http://www.opengroup.org/onlinepubs/007908...01_014_1985_002 :
The sed utility supports the basic regular expressions described in the XBD specification, Basic Regular Expressions , with the following additions:

http://www.opengroup.org/onlinepubs/007908...tml#tag_007_003 :
BRE Expression Anchoring
A BRE can be limited to matching strings that begin or end a line; this is called anchoring. The circumflex and dollar sign special characters will be considered BRE anchors in the following contexts:

1. A circumflex (^) is an anchor when used as the first character of an entire BRE. The implementation may treat circumflex as an anchor when used as the first character of a subexpression. The circumflex will anchor the expression (or optionally subexpression) to the beginning of a string; only sequences starting at the first character of a string will be matched by the BRE. For example, the BRE ^ab matches ab in the string abcdef, but fails to match in the string cdefab. The BRE \(^ab\) may match the former string. A portable BRE must escape a leading circumflex in a subexpression to match a literal circumflex.

2. A dollar sign ($) is an anchor when used as the last character of an entire BRE. The implementation may treat a dollar sign as an anchor when used as the last character of a subexpression. The dollar sign will anchor the expression (or optionally subexpression) to the end of the string being matched; the dollar sign can be said to match the end-of-string following the last character.

3. A BRE anchored by both "^" and "$" matches only an entire string. For example, the BRE ^abcdef$ matches strings consisting only of abcdef.


вы используете GNU'тый sed, с опцией -r, которая в этом GNUтом sed'е включает ERE, в которых действительно ^ и $ должны мочь быть частями subexpression.
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: sed и конец строки

Сообщение drBatty »


ага.
diesel писал(а):
21.01.2010 20:06
вы используете GNU'тый sed, с опцией -r, которая в этом GNUтом sed'е включает ERE, в которых действительно ^ и $ должны мочь быть частями subexpression.

ну да. а что не так?
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
gluk47
Сообщения: 297
Статус: Любитель гвоздей и микроскопов
ОС: Kubuntu 17.10

Re: sed и конец строки

Сообщение gluk47 »

Спасибо всем огромное, всё очень здорово прояснили :)
[gluk47@gluk47-desktop ~]$ ензу куищще
куищще is aliased to `reboot'
Спасибо сказали:
Аватара пользователя
diesel
Бывший модератор
Сообщения: 5989
ОС: OS X, openSuSE, ROSA, Debian

Re: sed и конец строки

Сообщение diesel »

drBatty писал(а):
21.01.2010 21:12
diesel писал(а):
21.01.2010 20:06
вы используете GNU'тый sed, с опцией -r, которая в этом GNUтом sed'е включает ERE, в которых действительно ^ и $ должны мочь быть частями subexpression.

ну да. а что не так?

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

Re: sed и конец строки

Сообщение drBatty »

diesel писал(а):
21.01.2010 22:51
drBatty писал(а):
21.01.2010 21:12
diesel писал(а):
21.01.2010 20:06
вы используете GNU'тый sed, с опцией -r, которая в этом GNUтом sed'е включает ERE, в которых действительно ^ и $ должны мочь быть частями subexpression.

ну да. а что не так?

строго говоря not-portable :)

к сожалению - да. вы правы :(
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

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