Dans cette édition,
Stéphane Chazelas POSIXifie (encore) ma sed
mise en forme en insérant une -e
coupure xpression et une autre -e
instruction xpression. Maintenant, je pourrais simplement lui demander pourquoi dans les commentaires, je suppose, mais c'est déjà la révision numéro 18 de cette réponse et presque toutes les précédentes étaient déjà grâce à des cadeaux similaires (si vous pouvez voir les commentaires supprimés, vous saurez quoi Je veux dire) . En outre, je pense que je suis assez proche pour comprendre pourquoi formuler cela d'une manière qui pourrait être plus généralement utile. Alors, j'espère ...
Je préfère généralement garder mes sed
-e
xpressions totales à un si je le peux, mais j'ai également une plus grande préférence pour me conformer aux spécifications aussi près que possible, surtout lorsque la différence ne dépasse pas a <space>
et an -e
. Mais je ne peux pas faire ça si je ne comprends pas pourquoi je devrais. Voici un bref aperçu de l'état actuel de ma compréhension:
la
' -e '
coupure peut remplacer de manière portative une coupure desed
script\n
ewline dans unesed
déclaration de ligne de commande ... Je suis certes floue sur la raisonl'accolade fermante dans une
sed
{
fonction}
doit être précédée d'une\n
coupure de ligne électronique comme indiqué ici:- Le
<right-brace>
doit être précédé d'un<newline>
et peut être précédé ou suivi de<blank>
caractères.
- Le
une
\n
pause ewline est nécessaire de la même suite à l'utilisation ...a
,b
,c
,i
,r
,t
,w
ou:
.
Mais je ne comprends pas clairement comment la définition de la {
fonction se }
rapporte à l' !
opérateur non. La seule mention que je trouve de l'opérateur de négation dans les états de spécification:
- 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.
Est-ce à dire que l'utilisation d'un a !
implique des {
accolades }
? Qu'en est-il des $!
commandes - devraient-elles également être séparées par des ' -e '
pauses? Est-ce ce qui a été abordé lorsque Stéphane a récemment POSIXifié ma réponse?
Je pense que c'est soit l' !
opérateur de négation, soit la b
déclaration de ranch qu'il aborde dans son édition - ou peut-être les deux à la fois - mais je ne sais pas et je voudrais le faire. Si ce n'est que la b
déclaration du ranch, alors je crois qu'un d
ferait à sa place et éliminerait le besoin de faire une ' -e '
pause, mais je préfère être certain avant de risquer une réponse POSIXifiée trois fois . Pouvez-vous m'aider?
Je l'ai risqué après tout , mais pas avec une grande certitude ...
b;n;:b
, vous vous connectez au label appelé";n;:b"
historique et POSIX seds (et GNU sed ne l'est pas à cet égard).:
- vous avez conduit cette maison il y a des mois. Mais je ne comprends pas vraiment pourquoi la deuxièmesed
commande a été similaire POSIXified .sed
est très peu claire pour moi. J'ai demandé des clarifications à quelques reprises dans le passé, mais je ne pense pas que cela ait été mis à jour en conséquence. Un bon test consiste à essayer avec le toolchest d'héritage (Solaris, dérivé de l'original et sur lequel la spécification POSIX est largement basée).s///
substitutions doivent accepter le chaînage avec un ; . cela devient flou autour des commandes qui doivent être délimitées par un retour à la ligne et comment-e
peuvent y rester dans ce cas - du moins c'est le cas pour moi. ive encore à tomber sur unsed
qui ne les interprète pas de manière assez interchangeable.;
avant une nouvelle ligne - une nouvelle ligne est très bien. Honnêtement, vous pouvez vous passer-e
entièrement de et de tout et simplement écrire un fichier comme#!/bin/sed
avec chaque commande sur une nouvelle ligne - ou ceux qui ne nécessitent pas de tels délimiteurs à la place délimités par;
. Ceux qui ne nécessitent habituellement les sauts de ligne sont ceux qui prennent entrée arbitraires -:
noms d'étiquettes et les commandes qui les réfèrent à desb
out
ou la fermeture}
Curlies pour les fonctions, our
ead etw
rite qui prennent args de nom de fichier. Ils doivent tous être portés de manière portative\n
.Réponses:
Il est donc grand temps que cette question ait une réponse, et, bien que j'aie fini par comprendre intuitivement comment le faire correctement dans presque tous les cas il y a quelque temps, je n'ai que très récemment réussi à concrétiser cette compréhension avec le texte de la norme. . En fait, il y est dit assez simplement - je l'ai simplement bêtement négligé plusieurs fois, je suppose.
Les parties pertinentes du texte se trouvent toutes sous le titre ...
Modification des commandes dans
sed
:Le texte de l' argument doit comprendre une ou plusieurs lignes. Chaque ligne
\n
électronique intégrée dans le texte doit être précédée d'une\
barre oblique inverse. Les autres barres obliques inverses dans le texte doivent être supprimées et le caractère suivant doit être traité littéralement.Les verbes de commande
r
etw
, et l'w
indicateur de las
commande, prennent un paramètre rfile (ou wfile ) facultatif , séparé de la lettre verbale ou de l'indicateur de commande par un ou plusieurs<blank>s
; les implémentations peuvent permettre une séparation nulle comme extension.Commande verbes autres que
{
,a
,b
,c
,i
,r
,t
,w
,:
et#
peut être suivi d'un;
point - virgule, en option<blank>s
, et un autre verbe de commande. Cependant, lorsque les
verbe de commande est utilisé avec l'w
indicateur, le suivre avec une autre commande de cette manière produit des résultats non définis....dans...
Options: plusieurs options
-e
et-f
peuvent être spécifiées. Toutes les commandes doivent être ajoutées au script dans l'ordre spécifié, quelle que soit leur origine.-e
script - Ajoutez les commandes d'édition spécifiées par l' argument option de script à la fin du script des commandes d'édition. L' argument-option de script doit avoir les mêmes propriétés que l' opérande de script , décrites dans la section OPERANDS .-f
script_file - Ajoutez les commandes d'édition dans le fichier script_file à la fin du script.Et enfin ...
Opérandes:
\n
électronique.Donc, quand vous le prenez tout à fait, il est logique que toute commande qui est facultativement suivie d'un paramètre arbitraire sans délimiteur prédéfini (par opposition à
s d sub d repl d flag
par exemple) devrait délimiter au niveau d'une ligne\n
électronique non échappée.On peut soutenir que le
;
est un délimiteur prédéfini, mais dans ce cas, l'utilisation de;
pour l'une des[aic]
commandes nécessiterait qu'un analyseur distinct soit inclus dans la mise en œuvre spécifiquement pour ces trois commandes - distinct, c'est-à-dire de l'analyseur utilisé pour[:brw]
, par exemple. Sinon, l'implémentation devrait exiger que la barre oblique inverse soit;
également échappée dans le paramètre text et cela ne fera que se compliquer à partir de là.Si je devais écrire un
sed
que je désirais être à la fois compatible et efficace, alors je ne serais pas écrire un tel analyseur séparé, je pense - sauf que peut - être[aic]
devrait gen une erreur de syntaxe si pas immédiatement suivi d'un\n
ewline. Mais c'est un problème de tokenisation simple - le cas du délimiteur de fin est généralement le plus problématique. Je voudrais simplement l'écrire ainsi:...et...
... se comporterait de manière très similaire, dans la mesure où le premier créerait et écrirait dans un fichier nommé:
... et le second ajouterait un bloc de texte à la ligne actuelle sur la sortie comme ...
... car les deux partageraient le même code d'analyse pour le paramètre.
Et en ce qui concerne la question
{ ... }
et$!
- eh bien, j'étais loin là-bas. Une seule commande précédée d'une adresse n'est pas une fonction mais plutôt une commande adressée. Presque toutes les commandes - y compris la{
définition de fonction}
sont spécifiées pour accepter/one/
ou/one/,/two/
adresser - à l'exception de la définition de#
commentaire et d':
étiquette . Et une adresse peut être soit un numéro de ligne ou un express régulier et peut être annulée avec!
. Donc tout ...... peut être suivi par une
;
et plusieurs commandes selon la norme, mais si plusieurs commandes sont requises pour une seule adresse, et que cette adresse ne doit pas être réévaluée après l'exécution de chaque commande, alors une{
fonction}
doit être utilisée comme:... où
{
ne peut pas être suivie sur la même ligne par une fermeture}
et qu'une fermeture}
ne peut se produire qu'en début de ligne. Mais si une commande contenue ne doit pas être suivie d'une ligne\n
électronique, elle n'a pas besoin non plus d'être dans la fonction. Ainsi, toutes less///
substitutions ci-dessus - et même l'}
accolade de fermeture , peuvent être portées par des;
points-virgules et d'autres commandes.Je continue de parler des
\n
délimiteurs ewline mais la question concerne plutôt les-e
instructions xpression, je sais. Mais les deux sont vraiment une seule et même chose, et la relation clé est qu'un script peut être soit un argument de ligne de commande littéral, soit un fichier avec l'un des deux-[ef]
, et que les deux sont interprétés comme des fichiers texte (qui sont spécifiés pour se terminer par un\n
ewline) mais aucun ne doit en fait se terminer par une\n
ewline. Par cela, je peux raisonnablement (j'espère) déduire qu'un\0NUL
argument délimité implique une ligne\n
terminale, et comme tous les arguments d'invocation obtiennent au moins) un\0NUL
délimiteur de toute façon, alors l'un ou l'autre devrait fonctionner correctement.En fait, dans la pratique, dans tous les cas sauf un où la norme spécifie un
\
retour à la ligne avec une barre oblique inversée qui devrait être requis, j'ai trouvé de façon portable ...... pour travailler aussi bien. Et dans tous les cas - encore une fois, dans la pratique - où une ligne
\n
électronique non échappée devrait être requise ...... a aussi fonctionné pour moi. La seule exception que je mentionne ci-dessus est ...
... qui ne fonctionne pour aucune implémentation dans aucun de mes tests. Je suis assez sûr que cela revient à l' exigence de fichier texte et au fait que cela
s///
vient avec un délimiteur et donc il n'y a aucune raison qu'une seule instruction devrait couvrir des\0NUL
arguments délimités.Donc, en conclusion, voici un bref aperçu des méthodes portables pour écrire plusieurs types de
sed
commandes:Pour n'importe lequel de
[aic]
:...ou...
Pour tous les
[:rwtb]
cas où le paramètre est facultatif (pour tous sauf:
) mais la ligne de délimitation\n
ne l'est pas . Notez que je n'ai jamais eu de raison d'essayer plusieurs paramètres d' étiquette de ligne comme cela serait utilisé avec[:tb]
, mais quew
riter / lirer
sur plusieurs lignes dans les paramètres du fichier [rw] est généralement accepté sans question parsed
s J'ai testé tant que la ligne\n
électronique intégrée est échappé avec une\
barre oblique inverse. Pourtant, la norme ne spécifie pas directement que les paramètres d' étiquette et de fichier [rw] doivent être analysés de manière identique au texteparamètres et ne fait aucune mention de\n
lignes électroniques concernant les deux premiers sauf s'il les délimite....ou...
... où ce qui
<space>
précède est facultatif[:tb]
.Enfin...
...ou...
... où l'une des commandes susmentionnées (à l'exception de
:
) accepte également au moins une adresse et qui peut être soit une/
expression rationnelle/
soit un numéro de ligne et peut être annulée!
, mais si plusieurs commandes sont nécessaires pour une seule évaluation de l' adresse, alors{
des}
accolades délimitant le contexte de la fonction doivent être utilisées. Une fonction peut contenir même plusieurs\n
commandes délimitées par ligne électronique, mais chacune doit être délimitée entre les accolades comme il en serait autrement.Et voilà comment écrire des
sed
scripts portables .la source