LINUX.ORG.RU

sed и два пробела

 


0

0

Есть код sed 's/\s[^$]/\\&/g'<<<"$VAR" — заменяет пробелы кроме пробела в конце строки на экранированные.
Проблема в том, что если где-то идёт 2 пробела, он один не экранирует. Как сделать, чтоб экранировал все?
И я даже не понимаю, почему он так делает.
Если без [^$] — то нормально. Но [^$] нужно.

★★★★★

Последнее исправление: teod0r (всего исправлений: 3)
Ответ на: комментарий от anonymous
% echo "wow" | sed -e 's/$/[I am the end]/'
wow[I am the end]
anonymous
()
Ответ на: комментарий от teod0r

я думал [^$] означает «следующий символ не является концом строки»

не означает. Внутри [скобок] свои правила.

emulek
()
Ответ на: комментарий от teod0r

моя понимает, причём по-моему.

и да, хватит уже

man 7 regex

Obsolete («basic») regular expressions differ in several respects. '|', '+', and '?' are ordinary characters and there is no equivalent for their functionality. The delimiters for bounds are «\{» and «\}», with '{' and '}' by themselves ordinary characters. The parentheses for nested subexpressions are «\(» and «\)», with '(' and ')' by themselves ordi‐ nary characters. '^' is an ordinary character except at the beginning of the RE or(!) the beginning of a parenthesized subexpression, '$' is an ordinary characterexcept at the end of the RE or(!) the end of a parenthesized subexpression, and '*' is an ordinary character if it appears at the beginning of the RE or the beginning of a parenthesized subexpres‐ sion (after a possible leading '^').

emulek
()
Ответ на: комментарий от emulek

Короч, понял, что тупой прост. В данном случае [] — character class. В нём не работают в качестве $, ^ anchors.
А ступил из-за предплоложения, что исходный примере

echo ' ' | sed 's/[^$]/Z/g'

таки отработал и осоноваясь на версии teod0r решил объяснить ему.
И если следовать логике мой пример должен быть таким:

% echo '123' | sed 's/[$]/хуй а не конец строки/g'
123

Сорь.

anonymous
()
Ответ на: комментарий от emulek

В данном случае [] — character class.

угу, там ^ работает как отрицание (в начале класса).

вот-бы ещё замутили такую ерунду в подвыражениях, было-бы хорошо.

emulek
()
Ответ на: ok от wakuwaku
% echo '$$$$\n'|sed 's/[^$]/Z/g'
$$$$

 % sed --version
sed (GNU sed) 4.2.2
...
anonymous
()
Ответ на: комментарий от wakuwaku

неужели так сложно представить LF? точно такой же символ

во первых, у тебя _два_ символа: «\» и «n». Во вторых, \n это, по мнению sed, особый символ. В строках sed \n _никогда_ не бывает(если его ты сам не засадишь).

В третьих, что ты доказываешь? Что мне трудно представить LF?

emulek
()
Ответ на: комментарий от emulek

_два_
особый символ

противоречишь себе.

_никогда_ не бывает

всегда есть Ox0A(EOL, почти, но LF у нас), кроме случаев, когда там только одна строка с виртуальным EOF на конце. EOF — место, EOL — вполне себе символ, либо же последовательность оных.

wakuwaku ★★★★
()
Ответ на: комментарий от wakuwaku

противоречишь себе.

читать не умеешь? Повторю: в строках sed \n _никогда_ не бывает(если его ты сам не засадишь).

всегда есть Ox0A(EOL, почти, но LF у нас), кроме случаев, когда там только одна строка с виртуальным EOF на конце. EOF — место, EOL — вполне себе символ, либо же последовательность оных.

ты неадекватен. Я же сказал «в строках sed».

И ты ответил: что ты доказываешь?

emulek
()
Ответ на: комментарий от wakuwaku

Sed получает строки из файлов, причём тут «строки sed»?

при том, что sed всегда грузит строку до EOL, потом обрабатывает, а потом выгружает.

Потому якорь $, это граница между последним символом и EOL. Сам EOL в строку сам никогда не попадает, потому что sed, как его встретит, так сразу начинает обрабатывать.

У меня

$ echo '$$$$\n'|sed 's/[^$]/Z/g'
$$$$ZZ
и тут нет ничего удивительного:

$ не матчится с [^$]

символы «\» и n матчатся, потому каждый символ меняется на Z. Получается $$$$ZZ.

И что?

emulek
()
Ответ на: комментарий от emulek

Хм, у меня zsh специфика была.

$ echo '$$$$\n'|sed 's/[^$]/Z/g'
$$$$ZZ

Понаставят всяких shell'ов, а потом толкуй с ними.

anonymous
()
Ответ на: комментарий от anonymous

У меня так:

~ % echo '$$$$\r\n'|sed 's/[^$]/Z/g'                                                                                                                                                                           [0]
$$$$Z

~ % echo '$$$$\n'|sed 's/[^$]/Z/g'                                                                                                                                                                             [0]
$$$$

~ % echo '$$$$\r'|sed 's/[^$]/Z/g'                                                                                                                                                                             [0]
$$$$Z
~ %                                                                                                                                                                                                            [0]

по кажется это фича zsh, он пытается быть eye candy

~ % echo -n '$$$$\r\n'>/tmp/tmp0002.tmp;sed 's/[^$]/Z/g' /tmp/tmp0002.tmp                                                                                                                                      [0]
$$$$Z
~ % 
~ $ echo -n '$$$$\r\n'>/tmp/tmp0002.tmp;sed 's/[^$]/Z/g' /tmp/tmp0002.tmp
$$$$ZZZZ~ $ 
wakuwaku ★★★★
()
Ответ на: комментарий от emulek

Лучше объясни мне это:

~ $ echo -en '$$$$\n'>/tmp/tmp0002.tmp;sed 's/[^$]/Z/g' /tmp/tmp0002.tmp
$$$$                                                                                                                                                                                                               
                                                                                                                                                                                                                   
~ $
~ $ echo -en '$$$$\r\n'>/tmp/tmp0002.tmp;sed 's/[^$]/Z/g' /tmp/tmp0002.tmp                                                                                                                                          
$$$$Z                                                                                                                                                                                                              
                                                                                                                                                                                                                   
~ $ 

wakuwaku ★★★★
()
Последнее исправление: wakuwaku (всего исправлений: 2)
Ответ на: комментарий от wakuwaku

см. выше. Мы возвращаемся к тому, что 0x0A — это LF.

какая разница, что такое LF?

может у вас огрызко-проблемы, или шелло-проблемы, мне пофиг, у меня Linux и bash.

\n == EOL == LF == 0x0A

\r == CR == 0xOD

колись, что у тебя.

emulek
()
Ответ на: комментарий от emulek
~ $ echo -en '$$$$\r\n'|hexdump
0000000 2424 2424 0a0d                         
0000006
~ $ echo -en '$$$$\n'|hexdump
0000000 2424 2424 000a                         
0000005
~ $ 

0x0d матчится sed'ом как EOL, а 0x0a — нет? Какие-то шеллопроблемы. Припоминаю читал книжку, там написание шелла как раз рассматривалось, в том числе обработка спецсимволов и escape-последовательностей.

wakuwaku ★★★★
()
Последнее исправление: wakuwaku (всего исправлений: 2)
Ответ на: комментарий от wakuwaku

0x0d матчится sed'ом как EOL, а 0x0a — нет?

в Linux строчки принято заканчивать 0x0a (\n), а 0x0d (\r) — просто символ, невидимый, и на моём терминале работает как CR

$ echo -e 'ABCDEF\rXYZ'
XYZDEF

emulek
()
Ответ на: комментарий от wakuwaku
$ echo -en '$$$$\r'>/tmp/tmp0002.tmp;sed 's/[^$]/Z/g' /tmp/tmp0002.tmp
$$$$Z

всё верно: \r это не доллар, и он матчится. И тут нет CR в выводе. На входе его тоже нет.

$ echo -e '$$$$\r'|sed 's/[^$]/Z/g'
$$$$Z
тоже самое, но красивее.

$ echo -e '$$$$\r\n\r'|sed 's/[^$]/Z/g'
$$$$Z
Z

как видишь, LF тут вообще в обработке не участвует, а напрямую едет на вывод.

$ echo -e '\n\n\r\n'|sed 's/[^$]/Z/g'


Z

emulek
()
Ответ на: комментарий от emulek

Твоя правда, наверное. Я под веществами. И эмм, мне было скучно, извини. :>

Так что, с \r это мои глюки, но \n sed всё же воспринимает как конец строки:

~ $  echo -en '$$$$\n\n\r\r11\n'|sed 's/$/Z/g'
$$$$Z
Z
11Z
~ $ 

Теперь можно обсудить то, что я сказал изначально, а именно \n преобразуется во вполне определённые байты, т.е. является спецсимволом (пусть и невидимым, но он там есть) LF, который нужно учитывать при разборе строк.

wakuwaku ★★★★
()
Последнее исправление: wakuwaku (всего исправлений: 1)
Ответ на: комментарий от wakuwaku

Я под веществами.

\n sed всё же воспринимает как конец строки

как ещё оно может воспринимать конец строки?

\n преобразуется во вполне определённые байты, т.е. является спецсимволом (пусть и невидимым, но он там есть) LF, который нужно учитывать при разборе строк.

в sed скрипте нельзя. Нет там такого символа. Я его юзаю как раз тогда, когда мне нужен какой-то маркёр, которого ТОЧНО не будет.

например:

$ echo "ABCDEFGH"|\
sed -r 's/^/\n/;s/$/\n/;bl;:l;s/(.*)(\n.)(.*)(.\n)(.*)/\1\4\3\2\5/;tl;s/\n//g'
HGFEDCBA
разворот строки наоборот, попробуй «улыбоктебедедмакар» например.

emulek
()
Ответ на: комментарий от wakuwaku

ну теперь изучай мой скрипт. Как изучишь — приходи ☺

emulek
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.