LINUX.ORG.RU

инересное поведение sed


0

0

Hi All!

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

echo "a???e\\fasdffffff" | sed -n 's/\([^\\]\)f/\1.f/pg'

в результате

a???e\fasd.ff.ff.ff

Такое ощущение, что, после замены следующая f уже не попадает под критерий совпадения, а как тогда будет выглядеть совпадение?

> Такое ощущение, что, после замены следующая f уже не попадает под критерий совпадения

Нет, это предыдущий символ подпадает под шаблон [^\\].

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

Что значит "предыдущий символ подпадает под шаблон [^\\]"? Просто перепишем в таком виде (даже чуть более общий случай):

echo "fаa???e\\ffasdffffff" | sed -n 's/\(^\|[^\\]\)f/\1.h/pg'

получаем

.hаa???e\f.hasd.hf.hf.hf

т.е. всякий раз когда встречается пара ff первая из них заменяется на .h, а вот вторая уже нет. Если присутствует третья f, то предыдущая (2ая) уже оказывается "предыдущим символом" и, разумеется, всё хорошо подставляется, но всё же, что не так со второй f? И как написать правильное регулярное выражение?

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

> echo "fаa???e\\ffasdffffff" | sed -n 's/\(^\|[^\\]\)f/\1.h/pg'

> получаем

> .hаa???e\f.hasd.hf.hf.hf

> т.е. всякий раз когда встречается пара ff первая из них заменяется на .h, а вот вторая уже нет. Если присутствует третья f, то предыдущая (2ая) уже оказывается "предыдущим символом" и, разумеется, всё хорошо подставляется, но всё же, что не так со второй f?

Замены

f -> .h # первая f

ff -> f.h # ff после /

df -> d.h # df после as

ff -> f.h # следующие ff

ff -> f.h # следующие ff

Последняя f остаётся.

> И как написать правильное регулярное выражение?

В регулярных выражениях для Perl и Python есть такая возможность, есть ли она для sed - не знаю :(.

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

Мысль понял.

Для sed'а ничего более умного чем

echo "fаa???e\\ffasdffffff" | sed -n -e 's/\(^\|[^\\]\)f/\1.f/g' -e 's/ff/f.f/gp'

не придумал (хотя и криво конечно)

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

to anonymous:
> А еще можно так: echo "fаa???e\\ffasdffffff" | sed 's/\(\\f\)\|\([^\\f]\?\)f/\1\2.f/g' :)

Предложение интересное, но с ошибкой. Пробую так:

echo "fаa???e\\f\\ffasdffffff" | sed 's/\(\\f\)\|\([^\\f]\?\)f/\1\2.f/g'

получаю

.fаa???e\f.f\f.f.fasd.f.f.f.f.f.f

стали появляться артифакты... :(

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