La documentation de POSIX sed a déclaré:
Une fonction peut être précédée d'un ou plusieurs '!' caractères, auquel cas la fonction doit être appliquée si les adresses ne sélectionnent pas l'espace de modèle. Zéro ou plusieurs caractères <vides> doivent être acceptés avant le premier '!' personnage. Il n'est pas précisé si les caractères <vides> peuvent suivre un '!' et les demandes conformes ne doivent pas suivre un "!" caractère avec des caractères <vides>.
Ainsi, avec n'importe quel sed POSIX, nous pouvons:
sed -e '/pattern/!d' file
C'est la même chose que d'écrire:
sed -e '/pattern/!!d' file
Et !!!d
et n
des points d'exclamation sont encore très bien (Testé avec trois sed
versions de heirloom toolchest ). Je ne vois aucun avantage entre plusieurs au lieu d'une seule exclamation.
Pourquoi la spécification a-t-elle permis cette syntaxe et comment est-elle utile dans une application réelle?
Il semble que GNU sed ne soit pas conforme dans ce cas, il se plaindra si nous utilisons plusieurs exclamations:
$ sed -e '/pattern/!!d' file
sed: -e expression #1, char 11: multiple `!'s
!
agit comme une bascule,/pattern/!!
est le même que/pattern/
et/pattern/!!!
est le même que/pattern/!
. Sur FreeBSD, plusieurs!
sont identiques à un seul.sed
scripts peuvent être générés . Étant donné un POSIXsed
, il devrait être très simple de créer un script pour l'écriture d'unsed
script. Et donc si vous aviez un déclencheur pour un cas qui devrait marquer une adresse!
non digne de votre action, vous pourriez même le déclencher plusieurs fois pour le même et toujours sortir avec les mêmes résultats.sed
ne le sont pas.Réponses:
sed
L'API est primitive - et c'est par conception. Au moins, il est resté primitif par sa conception - je ne peux pas dire s'il a été conçu primitivement au début. Dans la plupart des cas, l'écriture d'unsed
script qui, lorsqu'il est exécuté, produira un autresed
script est en effet une question simple.sed
est très souvent appliqué de cette manière par des préprocesseurs macro tels quem4
et / oumake
.(Ce qui suit est un cas d'utilisation hautement hypothétique: il s'agit d'un problème conçu pour convenir à une solution. Si cela vous semble un peu exagéré, c'est probablement parce qu'il l'est, mais cela ne le rend pas nécessairement moins valide.)
Considérez le fichier d'entrée suivant:
Si nous voulions écrire un
sed
script qui ajouterait le mot- case à la fin de chaque mot approprié dans le fichier d'entrée ci-dessus uniquement s'il pouvait être trouvé sur une ligne dans le contexte approprié , et nous souhaitions le faire le plus efficacement possible ( comme cela devrait être notre objectif, par exemple, lors d'une opération de compilation), nous devons donc éviter autant que possible d' appliquer des/
expressions rationnelles/
.Une chose que nous pourrions faire est de pré-éditer le fichier sur notre système en ce moment et de ne jamais appeler
sed
du tout pendant la compilation. Mais si l'un de ces mots dans le fichier doit ou ne doit pas être inclus en fonction des paramètres locaux et / ou des options de compilation, le faire ne serait probablement pas une alternative souhaitable.Une autre chose que nous pourrions faire est de traiter le fichier maintenant contre les expressions rationnelles. Nous pouvons produire - et inclure dans notre compilation - un
sed
script qui peut appliquer des modifications en fonction du numéro de ligne - ce qui est généralement un itinéraire beaucoup plus efficace à long terme.Par exemple:
... qui écrit la sortie sous forme de
sed
script et qui ressemble à ...Lorsque cette sortie est enregistrée dans un fichier texte exécutable sur ma machine nommée
./bang.sed
et exécutée comme./bang.sed ./infile
, la sortie est:Maintenant, vous pourriez me demander ... Pourquoi voudrais-je faire ça? Pourquoi ne devrais-je pas simplement ancrer
grep
des matchs? Qui utilise la camel case de toute façon? Et à chaque question à laquelle je ne pouvais que répondre, je n'en ai aucune idée ... parce que non. Avant de lire cette question, je n'avais jamais personnellement remarqué le multi-! analyse syntaxique dans la spécification - je pense que c'est une prise assez soignée.Le multi-! Cependant, cela a immédiatement eu un sens - une grande partie de la
sed
spécification est orientée vers dessed
scripts simplement analysés et générés simplement . Vous trouverez probablement les\n
délimiteurs ewline requis pour[wr:bt{]
avoir beaucoup plus de sens dans ce contexte, et si vous gardez cette idée à l'esprit, vous pourriez mieux comprendre certains autres aspects de la spécification - (comme l':
acceptation d'aucune adresse et leq
refus de accepter plus de 1) .Dans l'exemple ci - dessus , je vous écris une certaine forme de
sed
scénario qui ne peut jamais être lu une fois. Si vous le regardez attentivement, vous remarquerez peut-être que lors de lased
lecture du fichier d'édition, il progresse d'un bloc de commande à l'autre - il ne se dérive jamais ou ne termine son script d'édition jusqu'à ce qu'il soit complètement terminé avec son fichier d'édition.Je considère que multi-! les adresses pourraient être plus utiles dans ce contexte que dans certains autres, mais, en toute honnêteté, je ne peux pas penser à un seul cas dans lequel j'aurais pu l'utiliser à bon escient - et moi
sed
beaucoup. Je pense également qu'il convient de noter que les deux GNU / BSDsed
ne parviennent pas à le gérer comme spécifié - ce n'est probablement pas un aspect de la spécification qui est très demandé, et donc si une implémentation l'ignore, je doute très sérieusement que leurs bugs @ box souffriront terriblement en conséquence.Cela dit, le fait de ne pas gérer cela comme spécifié est un bogue pour toute implémentation qui prétend être conforme, et je pense donc que l'envoi d'un e-mail aux boîtes de développement pertinentes est nécessaire ici, et j'ai l'intention de le faire si vous ne le faites pas.
la source
!
va être supprimé dans la prochaine spécification , que se passe-t-il ici!