LINUX.ORG.RU

Регулярные выражения. sed vs grep. Запутался.

 


1

2

Цель: найти или заменить все слова, состоящие более чем из одного символа.

grep (работает):

echo "a aa aaa a c v aaa abc bbb n hhy" | grep  -P "[a-z]{2,}"
sed (не работает):
echo "a aa aaa a c v aaa abc bbb n hhy" | sed -r "s/[a-z]{1}//g"
Почему sed не работает?

Заменяем любой символ, состоящий из одного символа на пустоту. Но он заменяет все.

★★★

Пробел — это тоже «любой символ». (UPD: хотя в данном контексте это не играет роли, см. PS ниже)

echo "a aa aaa a c v aaa abc bbb n hhy" | sed "s/\<[[:alpha:]]\>//g"
 aa aaa    aaa abc bbb  hhy

PS: точнее, любое слово состоит из односимвольных последовательностей. sed их чесно и заменяет.

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

Уже не первый раз читаю у тебя в седе угловые скобки, но в мане о них ни слова, потому имею к тебе два вопроса: где почитать (сформулировать поисковой запрос так и не смог) про угловые скобки и это гнутый сед (ЕМНИП, у тебя гнутый не основной)?

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

Не помню, где и когда я их надыбал. Вот тебе выписка из мана:

There are two special cases** of bracket expressions: the bracket
expressions ‘[[:<:]]’ and ‘[[:>:]]’ match the null string at the
beginning and end of a word, respectively.  A word is defined as a
sequence of characters starting and ending with a word character which is
neither preceded nor followed by word characters.  A word character is an
alnum character (as defined by isalnum(3)) or an underscore.  This is an
extension, compatible with but not specified by POSIX, and should be used
with caution in software intended to be portable to other systems.  The
additional word delimiters ‘\<’ and ‘\>’ are provided to ease
compatibility with traditional SVR4 systems but are not portable and
should be avoided.

ref: http://mdoc.su/o/re_format

Т.ч. кошернее их заменить на [[:<:]] и [[:>:]], но это на 5 символов больше. ;) Ещё можно использовать \b.

UPD: гуглить по regex word boundary

beastie ★★★★★ ()
Последнее исправление: beastie (всего исправлений: 1 )
Ответ на: комментарий от beastie
  This is an extension, compatible with but not specified by POSIX,
and should be used with caution in software intended to be portable
to other systems.

Кстати, в GNU-тых sed и grep как раз форма '[[:<:]]' и не работает, а '\<' упоминается только в grep(1), но ни в sed(1), ни в regex(7) ничего нет.
Как раз случай «медвежьей услуги».

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

За ссылку благодарю.

гуглить по regex word boundary

А эту магию я пока ниасилил.

Кстати, я тут подумал, что s/\<[[:alpha:]]\>\s*//g было бы немного красивее.

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

ни в sed(1), ни в regex(7) ничего нет.

Потому я и попросил этим в меня кинуть.

в GNU-тых sed и grep как раз форма '[[:<:]]' и не работает

Но \</\> работают, а описание, кинутое выше, этого не исключает, а мне нужно было именно оно.

r3lgar ★★★★★ ()

У меня оба твоих однострочника не работают — grep не режет ничего, а sed режет абсолютно всю строку. ЧЯДНТ?

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

Это говорит только о не очень высоком качестве gnu документации.

beastie ★★★★★ ()

Всё правильно работает, sed оставил только пробелы. Если в grep указать {1}, он тоже выделит все символы, а не только слова из 1-го символа.

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