Newline in sed su Mac OS X.


44

Trovo che \nnon funzioni in sed con Mac OS X. In particolare, supponiamo che io voglia dividere le parole separate da un singolo spazio in linee:

# input
foo bar

Io uso,

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

Ma il risultato è stupido, \nnon è sfuggito!

foonbar

Dopo aver consultato Google, ho trovato una soluzione alternativa :

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

Dopo aver letto l'articolo, non riesco ancora a capire cosa \'$'\n/g'significhi. Qualcuno può spiegarmelo o se esiste un altro modo per farlo? Grazie!


probabilmente funzionerebbe anche questo:echo "foo bar" | tr ' ' '\n'
Glenn Jackman,

3
Grazie per il consiglio. Ma attualmente uso solo il caso sopra come esempio, ho bisogno di sapere come sfuggire a \n.
Ivan ZG Xiao,

Risposte:


27

È possibile brew install gnu-sede sostituire le chiamate sedcon gsed.

Se non vuoi anteporre la "g" a sed, puoi brew install gnu-sed --with-default-namese basta chiamare sed.

(Modifica: bandiera della birra aggiornata, punta del cappello a Clément.)


Usare lo stesso software su tutte le piattaforme è molto più semplice (finalmente per me) che gestire ogni specificità della versione per Mac. Attenzione, l'opzione è ora --with-default-namese non --default-names . Tuttavia, questa opzione non ha funzionato sulla mia installazione, quindi ho dovuto inserire un alias gsed=sedmio ~/.profileper farlo funzionare.
Clément,

4
Questa è una brutta soluzione. Non spiega perché sedsu OS X si comporti nel modo in cui lo fa e rende più corretto il presupposto errato gnu-sed. Non essere un drogato di GNU e attenersi agli standard POSIX per evitare problemi a lungo termine.
octosquidopus,

È come Apple dovrebbe far funzionare il suo sistema operativo per impostazione predefinita. Perché usare il nome di un programma e poi farlo funzionare in modo diverso?
Perdo

@rascio - perché OS X è simile a BSD e Linux è simile a Linux.
iAdjunct,

@rascio Penso che scoprirai che GNU sed è il nuovo arrivato; BSD sed risale al 1979 (vedi en.wikipedia.org/wiki/Version_7_Unix ).
Duncan Bayne,

24

Funzionerebbero anche:

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

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

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

La sed di OS X non interpreta \nil modello di sostituzione, ma puoi usare un avanzamento di riga letterale preceduto da un carattere di continuazione della linea. La shell sostituisce $'\n'con un avanzamento di riga letterale prima dell'esecuzione del comando sed.


4
Perché sed $'s/ /\\\n/g'funziona, ma no sed $'s/\\\n/ /g'?
Alec Jacobson,

1
@alec Non puoi usare sednemmeno in linux / unix per rimuovere le nuove righe perché è analizzato / diviso su ogni nuova riga. Se lo esegui in linux / unix, non farà nulla neanche:echo -e 'foo\nbar' | sed 's/\n//'
wisbucky,

10

La soluzione alternativa trovata passa una singola stringa di argomento a sed -e.

Tale argomento finisce per essere una stringa nel familiare s/ / /gformato sed .

Quella stringa viene creata in due parti, una dopo l'altra.

La prima parte è citata in '...'forma.

La seconda parte è citata nella $'...'forma.

La 's/ /\'parte ottiene le virgolette singole rimosse, ma per il resto passa a sed proprio come appare sulla riga di comando. Cioè, la barra rovesciata non viene mangiata da bash, viene passata a sed.

La $'\n/g'parte ottiene il simbolo del dollaro e le virgolette singole vengono cancellate e \nviene convertito in un carattere di nuova riga.

Tutti insieme, l'argomento diventa

s / / \ newline/ g

[È stato divertente. Ci è voluto un po 'per scartarlo. +1 per una domanda interessante.]


7

L'espressione $'...'è un bash-ismo che produce ...con l'espansione delle sequenze di escape standard. Th \'prima significa solo una barra rovesciata seguita dalla fine della sezione citata, la stringa risultante è s/ /\. (Sì, puoi cambiare le virgolette nel mezzo di una stringa; non termina la stringa.)

Lo standard POSIX sedaccetta solo \ncome parte di un modello di ricerca. OS X usa FreeBSD sed, che è rigorosamente conforme a POSIX; GNU, come al solito, aggiunge cose extra e quindi tutti gli utenti Linux pensano che sia una sorta di "standard" (forse sarei più colpito se entrambi avessero un processo standard).


Ora capisco la $'...'parte. Ma ... che cos'è s/ /\ ? Cosa intendi con switch quoting?
Ivan ZG Xiao,

2
'...'è un tipo di quotazione di shell; $'...'è un altro. C'è anche "..."e \xper citare un singolo personaggio. Puoi combinarli in una sola parola, che è ciò che è stato fatto lì, passando da una ''stringa normale a una $''stringa per tradurre il \n. Per il resto, sta costruendo un sedcomando ( s/text/replacement/flags). In questo caso il comando viene avviato, includendo una barra rovesciata alla fine per proteggere la nuova riga letterale che viene $'\n/g'aggiunta. Il risultato è sostituire tutti gli /gspazi ( bandiera) con le nuove linee.
Geekosaur,

1

È molto facile vedere visivamente cosa sta succedendo. Fai semplicemente eco alla stringa!

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

risultati in

s/$/\
/g

che equivale a s/$/\newline/g

Se non avessi avuto il extra \prima di newline, la shell interpreterebbe newlineprematuramente la fine del comando.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.