J'utilise donc 'sed' sur linux depuis un certain temps, mais j'ai eu un peu de difficulté à l'utiliser sur OSX depuis que 'POSIX sed' et 'GNU sed' ont tellement de petites différences. Actuellement, j'ai du mal à insérer une ligne de texte après un certain numéro de ligne. (dans ce cas, ligne 4)
Sur Linux, je ferais quelque chose comme ceci:
sed --in-place "4 a\ mode '0755'" file.txt
Donc, sur OSX, j'ai essayé ceci:
sed -i "" "4 a\ mode '0755'" file.txt
Cependant, cela continue de me donner une erreur «caractères supplémentaires après \ à la fin d'une commande». Des idées ce qui ne va pas ici? Ai-je une faute de frappe? Ou ne comprends-je pas une autre différence entre les versions de sed?
Réponses:
À proprement parler, la spécification POSIX pour
sed
requiert une nouvelle ligne aprèsa\
:Cela rend l' écriture one-liners un peu d'une douleur, ce qui est probablement la raison de ce qui suit extension GNU au
a
,i
et lesc
commandes:Ainsi, pour être portable avec votre
sed
syntaxe, vous aurez besoin d'inclure une nouvelle ligne après lea\
quelque part. Le moyen le plus simple consiste à insérer simplement un saut de ligne entre guillemets:(où
$
et>
sont les invites du shell). Si vous trouvez qu'un problème,bash
[1] a la$' '
syntaxe de citation pour insérer des échappements de style C, utilisez simplement[1] et mksh (r39b +) et certains shells bourne non bash (par exemple, / bin / sh dans FreeBSD 9+)
la source
Comme décrit dans cette réponse , il est utile lors de l'utilisation de commandes sed comme
i
eta
d'utiliser plusieurs-e "..."
clauses. Chacune de ces clauses sera considérée comme étant séparée par des retours à la ligne. Lesi
et lesa
commandes sont difficiles à utiliser dans des scripts sed en ligne autrement (ils sont conçus pour être utilisés dans un fichier script sed multiligne appelé à l' aidesed -f file ...
). Il semble que vous ne puissiez pas utiliser la nouvelle ligne implicite introduite à la fin d'une-e
clause pour séparer laa\
et la ligne de texte à ajouter. Mais vous pouvez l'utiliser pour terminer la ligne de texte à ajouter.Dans ce cas précis, ce que vous essayez de faire pourrait en fait être accompli avec une seule
-e ...
clause. Il vous suffit d'utilisera
correctement la commande. Selon la norme POSIX,a
doit être suivi d'un\
, puis qui doit être suivi d'un retour à la ligne, puis le reste de la ligne suivante sera inséré (jusqu'à ce qu'un retour à la ligne ou la fin de la-e
clause soit rencontré). Vous pourriez donc faire:la source
GNU sed semble être beaucoup plus utilisé que POSIX sed, basé sur des exemples / tutoriels que j'ai utilisés de toute façon.
J'ai trouvé qu'il est beaucoup plus facile d'installer GNU sed sur n'importe quelle machine OSX que j'utilise. Si vous êtes intéressé, la meilleure façon de le faire est de l'installer via Homebrew .
Vous pouvez soit simplement
$ brew install gnu-sed
, soit obtenir tous les utilitaires GNU courants avec$ brew install coreutils
.Ensuite, lorsque vous rencontrez un problème de syntaxe avec
date
ou un autre programme, vous pouvez simplement utiliser la version GNU. Finalement, j'ai simplement décidé qu'il était plus facile de toujours utiliser les versions GNU et de les mettre plus tôt que les versions système dans monPATH
.la source
Perl ne souffre pas de telles particularités GNU dépendantes de la plate-forme vs non-GNU vs "propriétaires". Vous pourriez faire:
Le
-n' option creates a loop that reads every line of the input file. Unlike its cousin
-p(not used here) it doesn't automatically print every line read. The
-iinvokes in-place replacement. The argument to
-i(viz. ".old") can be dropped or changed. It leaves a backup of the unmodified file. The -e
signale le début du script.Le
$.
désigne le numéro de ligne, en commençant par la ligne-1. Ainsi, la ligne de commande lit «fichier» et lorsque le numéro de ligne est égal à 4, il imprime cette ligne suivie de tout ce que vous voulez injecter.Je m'empresse d'ajouter que Perl doit ses racines à
sed
AWK et C, donc la syntaxe des substitutions simples, etc. n'est pas une courbe d'apprentissage très abrupte.la source
perl -wlpi.old -e 'print "mode 0755" if $. == 5' file.txt
. Le-p
commutateur fonctionne bien ici (puisque nous voulons imprimer chaque ligne); il suffit de changer la logique de "imprimer après la ligne 4" à "imprimer avant la ligne 5". Et le-l
commutateur fait en sorte que "\ n" soit imprimé automatiquement avec chaqueprint
, vous n'avez donc pas à l'imprimer vous-même.