Новые строки в sed на Mac OS X

44

Я считаю, что \nэто не работает в sed под Mac OS X. В частности, скажем, я хочу разбить слова, разделенные одним пробелом, на строки:

# input
foo bar

Я использую,

echo "foo bar" | sed 's/ /\n/'

Но результат тупой, тот \nне избежал!

foonbar

После того, как я посоветовался с Google, я нашел обходной путь :

echo 'foo bar' | sed -e 's/ /\'$'\n/g'

Прочитав статью, я все еще не могу понять, что \'$'\n/g'значит. Может кто-нибудь объяснить это мне, или есть ли другой способ сделать это? Благодарность!

Иван З. Г. Сяо
источник
это, вероятно, тоже будет работать:echo "foo bar" | tr ' ' '\n'
Гленн Джекман
3
Спасибо за совет. Но в настоящее время я просто использую приведенный выше случай в качестве примера, мне нужно знать, как избежать a \n.
Иван З. Г. Сяо
Возможный дубликат: stackoverflow.com/questions/21621722/…
hyiltiz

Ответы:

27

Вы можете brew install gnu-sedи заменить вызовы sedс gsed.

Если вы не хотите ставить перед «g» sed, вы можете brew install gnu-sed --with-default-namesпросто позвонить sed.

(Редактировать: обновленный флаг заваривания, шляпная подсказка для Clément.)

Ахмед Фасих
источник
Использовать одно и то же программное обеспечение на всех платформах намного проще (наконец-то для меня), чем иметь дело со всеми особенностями версии для Mac. Осторожно, вариант есть сейчас --with-default-namesи нет --default-names . Тем не менее, эта опция не работала на моей установке, поэтому мне пришлось вставить alias gsed=sedв ~/.profileнее, чтобы она работала.
Clément
4
Это уродливый обходной путь. Это не объясняет, почему sedв OS X ведет себя так, как она делает, и делает неправильное предположение, которое gnu-sedявляется более правильным. Не будьте наркоманом GNU и придерживайтесь стандартов POSIX, чтобы избежать проблем в долгосрочной перспективе.
octosquidopus
Именно так Apple должна заставить свою ОС работать по умолчанию. Зачем использовать название программы, а затем заставить ее работать по-другому? Я теряю час из-за этого ...
Расио
@rascio - потому что OS X похожа на BSD, а Linux похожа на Linux.
iAdjunct
@rascio Я думаю, вы обнаружите, что GNU sed - новичок; BSD sed восходит к 1979 году (см. En.wikipedia.org/wiki/Version_7_Unix ).
Дункан Бэйн
24

Это также будет работать:

echo 'foo bar' | sed 's/ /\
/g'

echo 'foo bar' | sed $'s/ /\\\n/g'

lf=$'\n'; echo 'foo bar' | sed "s/ /\\$lf/g"

OS X sed не интерпретирует \nшаблон замены, но вы можете использовать буквальный перевод строки, которому предшествует символ продолжения строки. Оболочка заменяется $'\n'буквальным переводом строки перед выполнением команды sed.

LRI
источник
4
Почему sed $'s/ /\\\n/g'работает, а нет sed $'s/\\\n/ /g'?
Алек Якобсон
1
@alec Вы не можете использовать sedдаже в linux / unix для удаления новых строк, потому что их анализируют / разбивают на каждой новой строке. Если вы запустите это в linux / unix, он тоже ничего не сделает:echo -e 'foo\nbar' | sed 's/\n//'
wisbucky
10

Обходной путь, который вы нашли, передает строку с одним аргументом sed -e.

Этот аргумент заканчивается строкой в ​​привычном s/ / /gформате sed .

Эта строка создается в двух частях, одна за другой.

Первая часть цитируется в '...'форме.

Вторая часть цитируется по $'...'форме.

's/ /\'Часть получает одинарные кавычки содранных, но в противном случае проходит через к СЭДУ так же , как это выглядит в командной строке. То есть обратная косая черта не съедается bash, она передается в sed.

$'\n/g'Часть получает знак доллара и одинарные кавычки содранных, и \nпреобразуется в символ новой строки.

Все вместе, аргумент становится

с / / \ newline/ г

[Это было весело. Потребовалось время, чтобы развернуть это. +1 за интересный вопрос.]

Spiff
источник
7

Выражение $'...'является bash-ism, который производит ...с расширенными стандартными escape-последовательностями. Th , \'прежде чем это просто означает обратную косую черту , за которой следует в конце цитируемого раздела, результирующая строка s/ /\. (Да, вы можете переключать кавычки в середине строки; она не заканчивается строкой.)

Стандарт POSIX sedпринимает только \nкак часть шаблона поиска. OS X использует FreeBSD sed, которая строго соответствует POSIX; GNU, как обычно, добавляет дополнительные вещи, и тогда все пользователи Linux думают, что это своего рода «стандарт» (возможно, я был бы более впечатлен, если бы у кого-то из них был процесс стандартизации).

geekosaur
источник
Теперь я понимаю $'...'часть. Но ... что это s/ /\ ? Что вы имеете в виду switch quoting?
Иван З. Г. Сяо
2
'...'является одним из видов цитирования оболочки; $'...'Другой. Там же "..."и \xпроцитировать один символ. Вы можете объединить их в одно слово, что и делается, переключаясь с обычной ''строки на $''строку для перевода \n. В остальном, это сборка sedкоманды ( s/text/replacement/flags). В этом случае команда запускается, включая обратную косую черту в конце, чтобы защитить буквальный символ новой строки, который $'\n/g'добавляется. Результатом является замена всех /gпробелов ( флагов) на новые строки.
geekosaur
1

Там очень легко визуально увидеть, что происходит. Просто повторить строку!

echo 's/$/\'$'\n/g'

результаты в

s/$/\
/g

что эквивалентно s/$/\newline/g

Если у вас не было лишнего \до newline, оболочка newlineпреждевременно интерпретирует конец команды.

wisbucky
источник