it-swarm.it

Differenze tra sed su Mac OSX e altre sed "standard"?

Sto riscontrando alcuni problemi nell'uso di una risposta fornita su questo sito per questa domanda su un comando sed per sostituire una riga vuota con altre due righe di contenuto , ed è stata sollevata se il comando sed su Mac Il sistema operativo (10.6.7 per me) è diverso. Non penso che lo sia, ma mi chiedevo se gli altri su questo sito pensassero diversamente.

67
Peter Grill

Il comportamento dei programmi di utilità Shell differisce in modo minore tra le varianti unix. Esistono molte varianti nix , con complessostoria . Ci sono sforzi di standardizzazione come lo POSIX standard e il suo superset lo specifica UNIX singola . La maggior parte dei sistemi oggi implementa POSIX: 2001, noto anche come Single UNIX Specification versione , con deviazioni minori e molte estensioni. La specifica Single Unix non è un tutorial, ma la versione 3 è leggibile se hai già un'idea di cosa sta facendo un comando. Puoi consultarlo per sapere se alcune funzionalità sono standard o un'estensione di un particolare sistema.

La maggior parte degli utenti unix usa Linux e non ha usato nessuna altra variante. Linux viene fornito con GNU utility, che spesso hanno molte estensioni allo standard. Quindi troverai un sacco di codice là fuori che funziona su Linux ma non su altri unices, perché si basa su quelle estensioni.

Per quanto riguarda sed, consultare specifica sed Single Unix per il minimo che ogni sistema dovrebbe supportare, pagina man sul proprio sistema per ciò che supporta l'implementazione e - Manuale GNU sed per ciò che la maggior parte delle persone usa.

Una delle estensioni non standard in GNU sed supporta più comandi eseguiti insieme. Ad esempio, questo GNU sed stampa tutte le righe contenenti un a, ma cambia b in c prima:

sed -ne '/a/ {s/b/c/g; p}'

{ E } Sono in realtà comandi separati, quindi per la completa portabilità, è necessario specificarli su righe separate (in un file) o in argomenti -e Separati (sul riga di comando). La mancanza di un separatore di comandi dopo { E l'uso di ; Come separatore di comandi sono estensioni comuni. La mancanza di un separatore di comandi prima di } È un'estensione meno comune. Questo è conforme allo standard:

sed -n -e '/a/ {' -e 's/b/c/g' -e p -e '}'

Questo è non standard ma comunemente accettato:

sed -ne '/a/ { s/b/c/g; p; }'

Un'altra estensione non standard ma comune è l'uso di \n Per indicare una nuova riga in un testo sostitutivo s (l'uso in una regexp è standard). Il metodo portatile è quello di includere backslash-newline nello script sed. Un'altra estensione comune è \+, \? E \| In regexps per indicare uno o più, al massimo uno e alternanza; espressioni regolari di base portatili non hanno nessuna di queste. Ad esempio, il primo comando è un modo non portatile di sostituire sequenze contigue di spazi bianchi con una nuova riga; il secondo comando è un equivalente conforme agli standard.

sed -e 's/ \+/\n/'
sed -e 's/  */\
/'

OS X attualmente viene fornito con una versione di FreeBSD sed del 2005. La maggior parte delle differenze seguenti si applicano anche ad altre versioni di BSD sed.

La sed di OS X usa -E per ERE e GNU sed usa -r. -E è un alias per -r in GNU sed (aggiunto in 4.2, non documentato fino alla 4.3). Le versioni più recenti di FreeBSD e NetBSD sed supportano entrambi -E e -r. OpenBSD sed supporta solo -E.

-i '' funziona con sed di OS X ma non GNU sed. -i funziona con GNU sed, versioni recenti di NetBSD, OpenBSD sed, ma non con OS X sed. -i -e funziona con entrambi ma nel caso di FreeBSD sed esegue un backup del file originale con -e aggiunto al nome del file (e non devi passare più di un'espressione a sed).

GNU sed interpreta sequenze di escape come \t, \n, \001, \x01, \w, e \b. La sed di OS X e la sed POSIX interpretano solo \n (ma non nella parte sostitutiva di s).

GNU sed interpreta \|, \+, e \? in BRE ma sed di OS X e POSIX no. \(, \), \{, e \} sono POSIX BRE.

GNU sed consente di omettere ; o una nuova riga prima di } ma sed di OS X no.

i (insert), a (append) e c (modifica) devono essere seguiti da una barra rovesciata e da una nuova riga nella sed di OS X e nella POSIX ma non in GNU sed. GNU sed aggiunge una nuova riga mancante dopo il testo inserito da i, a o c ma sed di OS X no. Ad esempio sed 1ia è a GNU alternativa a sed $'1i\\\na\n'.

Per esempio printf a|sed -n p aggiunge una nuova riga nella versione di OS X ma non in GNU sed.

Il sistema operativo sed X di OS non supporta i modificatori I (senza distinzione tra maiuscole e minuscole) o M (multilinea). Le versioni più recenti di FreeBSD sed supportano I.

La sed di OS X non supporta -s (--separate), -u (--unbuffered), o -z (--null-data).

Un'opzione BSD che non è supportata da GNU sed è -a, che rende w un file invece di troncare un file.

Esempi di GNU comandi sed che non funzionano con sed di OS X:

sed /pattern/,+2d # like `sed '/pattern/{N;N;d;}'`
sed -n 0~3p # like `awk NR%3==0`
sed /pattern/Q # like `awk '/pattern/{exit}1'` or `sed -n '/pattern/,$!p'`
sed 's/\b./\u&/g' # \u converts the next character to uppercase
sed 's/^./\l&/' # \l converts the next character to lowercase
sed -i '1ecat file_to_prepend' file # e executes a Shell command
sed -n l0 # 0 disables wrapping
69
Lri

Il modo migliore che ho trovato per avere lo stesso lavoro di script sia su Linux che su Mac è di:

sed -i.bak -e 's/foo/bar/' -- "${TARGET}" &&
  rm -- "${TARGET}.bak"
6
vikrantt