Нові рядки в 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
Дякую за пораду. Але в даний час я просто використовую вищезгаданий випадок як приклад, мені потрібно знати, як уникнути \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щоб зробити його роботу.
Клімент

4
Це потворне вирішення. Це не пояснює, чому sedв OS X поводиться так, як це робиться, і робить неправильне припущення, що gnu-sedє більш правильним. Не будьте наркоманкою GNU та дотримуйтесь стандартів POSIX, щоб уникнути проблем у довгостроковій перспективі.
октября о 15:13

Саме так Apple повинна змусити свою ОС працювати за замовчуванням. Навіщо використовувати назву програми, а потім змусити її працювати по-іншому? Я витрачаю годину через це ...
rascio

@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"

Sed X OS не інтерпретується \nв схемі заміни, але ви можете використовувати буквальне подання рядків, перед яким проходить символ продовження рядка. Оболонка замінюється $'\n'буквальною передачею рядка перед виконанням команди sed.


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/ /\'Частина отримує одинарні лапки зідраних, але в іншому випадку проходить через до СЕДУ так само , як це виглядає в командному рядку. Тобто, зворотний нахил не їдять баш, він передається sed.

The $'\n/g'Частина отримує знак долара і одинарні лапки зідраних, і \nперетворюється на символ нового рядка.

Всі разом аргумент стає

s / / \newline / g

[Це було весело. Знадобився час, щоб розгорнути це. +1 для цікавого питання.]


7

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

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


Тепер я розумію $'...'частину. Але ... що таке 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передчасно інтерпретувати як закінчення команди.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.