Новые строки в 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}|"