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

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

# input
foo bar

Я использую,

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

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

foonbar

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

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

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

5 ответов

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

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

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

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

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.

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

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

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

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

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

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

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

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

s / / \newline/ g

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

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

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

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

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

результаты в

s/$/\
/g

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

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

Этот обходной путь работает на Mac, и скрипт может быть выполнен также в Linux.

NL="\n"
if [[ $uname -eq "Darwin" ]]; then
    NL=$'\\\n'
fi

echo 'foo bar' | sed -e "s| |${NL}|" 

Немного более компактная форма ответа @max-zerbini:

[[ $(uname) -eq "Darwin" ]] && NL=$'\\\n' || NL="\n"
echo 'foo bar' | sed -e "s| |${NL}|" 
Другие вопросы по тегам