web-dev-qa-db-fra.com

Différences entre sed sur Mac OSX et sed "standard"?

J'ai des problèmes à utiliser une réponse fournie sur ce site pour cette question sur une commande sed pour remplacer une ligne vierge par deux autres lignes de conten , et elle a été affichée si la commande sed sur Mac OS (10.6.7 pour moi) est différent. Je ne pense pas que ce soit le cas, mais je me demandais si d'autres personnes sur ce site pensaient différemment.

67
Peter Grill

Le comportement des utilitaires Shell diffère de manière mineure entre les variantes Unix. Il existe de nombreuses variantes nix , avec un complexehistorique . Il existe efforts de normalisation tels que la norme POSIX et son surensemble la spécification UNIX unique . La plupart des systèmes implémentent aujourd'hui POSIX: 2001, également connu sous le nom de Single UNIX Specification version , avec des écarts mineurs et de nombreuses extensions. La spécification Single Unix n'est pas un tutoriel, mais la version 3 est lisible si vous avez déjà une idée de ce que fait une commande. Vous pouvez le consulter pour savoir si certaines fonctionnalités sont standard ou une extension d'un système particulier.

La majorité des utilisateurs d'Unix utilisent Linux et n'ont utilisé aucune autre variante. Linux est livré avec les utilitaires GNU , qui ont souvent de nombreuses extensions de la norme. Vous trouverez donc pas mal de code qui fonctionne sur Linux mais pas sur d'autres unités, car il repose sur ces extensions.

Concernant sed, consultez la spécification sed Single Unix pour le minimum que chaque système est censé supporter, la page de manuel sur votre système pour ce que votre implémentation supporte, et la - Manuel GNU sed pour ce que la plupart des gens utilisent.

L'une des extensions non standard de GNU sed prend en charge plusieurs commandes exécutées ensemble. Par exemple, ce programme GNU sed imprime toutes les lignes contenant un a, mais change d'abord b en c d'abord:

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

{ et } sont en fait des commandes distinctes, donc pour une portabilité complète, vous devez les spécifier sur des lignes distinctes (dans un fichier) ou dans des -e arguments (sur la ligne de commande). L'absence d'un séparateur de commandes après { et l'utilisation de ; comme séparateur de commandes sont des extensions courantes. L'absence d'un séparateur de commandes avant } est une extension moins courante. Ceci est conforme aux normes:

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

Ceci est non standard mais généralement accepté:

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

Une autre extension non standard mais courante est l'utilisation de \n pour signifier une nouvelle ligne dans un texte de remplacement s (l'utilisation dans une expression rationnelle est standard). La méthode portable consiste à inclure backslash-newline dans le script sed. Une autre extension courante est \+, \? et \| dans les expressions rationnelles pour signifier un ou plusieurs, au plus un et l'alternance; expressions régulières de base portables n'en ont aucune. Par exemple, la première commande est un moyen non portable de remplacer des séquences contiguës d'espaces blancs par une nouvelle ligne; la deuxième commande est un équivalent conforme aux normes.

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

OS X est actuellement livré avec un sed FreeBSD à partir de 2005. La plupart des différences ci-dessous s'appliquent également aux autres versions de sed BSD.

Sed de OS X utilise -E pour ERE et GNU sed utilise -r. -E est un alias pour -r in GNU sed (ajouté en 4.2, non documenté avant 4.3). Les versions plus récentes de FreeBSD et NetBSD sed prennent en charge les deux -E et -r. OpenBSD sed ne prend en charge que -E.

-i '' fonctionne avec sed d'OS X mais pas GNU sed. -i fonctionne avec GNU sed, versions récentes de NetBSD, OpenBSD sed, mais pas sed d'OS X. -i -e fonctionne avec les deux mais dans le cas de FreeBSD sed fait une sauvegarde du fichier d'origine avec -e ajouté au nom du fichier (et vous ne devez pas passer plus d'une expression à sed).

GNU sed interprète les séquences d'échappement comme \t, \n, \001, \x01, \w, et \b. Sed et POSIX sed d'OS X interprètent uniquement \n (mais pas dans la partie de remplacement de s).

GNU sed interprète \|, \+, et \? dans BRE, mais pas sed de OS X et sed de POSIX. \(, \), \{, et \} sont POSIX BRE.

GNU sed permet d'omettre ; ou une nouvelle ligne avant } mais pas sed de OS X.

i (insérer), a (ajouter) et c (changer) doivent être suivis d'une barre oblique inverse et d'une nouvelle ligne dans sed et OS POSIX sed d'OS X mais pas dans GNU sed. GNU sed ajoute une nouvelle ligne manquante après le texte inséré par i, a, ou c mais sed de OS X non. Par exemple sed 1ia est une alternative GNU à sed $'1i\\\na\n'.

Par exemple printf a|sed -n p ajoute une nouvelle ligne dans sed d'OS X mais pas dans GNU sed.

Sed d'OS X ne prend pas en charge les modificateurs I (insensible à la casse) ou M (multiligne). Les nouvelles versions de FreeBSD sed prennent en charge I.

Sed de OS X ne prend pas en charge -s (--separate), -u (--unbuffered), ou -z (--null-data).

Une option BSD non prise en charge par GNU sed est -a, ce qui fait que w s'ajoute à un fichier au lieu de tronquer un fichier.

Exemples de commandes GNU sed qui ne fonctionnent pas avec sed d'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

Le meilleur moyen que j'ai trouvé pour faire fonctionner le même script sur Linux et Mac est de:

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