2
votes

Correspondance conditionnelle et commande d'exécution avec décalage

Je trouve une commande bash pour un remplacement conditionnel avec offset. Les articles existants que j'ai trouvés sont des remplacements conditionnels sans offset ou avec un offset fixe .

Tâche: Si uid contient 8964 , puis insérez la ligne FORBIDDEN avant DOB.

Chaque fichier TXT ci-dessous représente un utilisateur, et il contient (dans le ordre suivant)

  1. une propriété (s)
  2. unique uid
  3. certaines qualité (s)
  4. unique DOB
  5. un lorem ipsum
  6. aléatoire

J'espère pouvoir transformer les fichiers suivants

sed: -e expression #1, char 0: unmatched `{'

en

sed '/^uid: [0-9]*8964[0-9]*$/{n;/^DOB: .*$/{iFORBIDDEN}}' file*.txt

Mon essai:

Si uid contient 8964 , alors faites une deuxième correspondance avec DOB et insérez FORBIDDEN ci-dessus DOB.

# file1.txt (uid doens't match 8964)
admin: false
uid: 123456
happy
movie
DOB: 6543-02-10
lorem ipsum
seo varis lireccuni paccem noba sako

# file2.txt (uid matches 8964)
citizen: true
hasSEAcct: true
uid: 289641
joyful hearty
final debug Juno XYus
magazine
FORBIDDEN
DOB: 1234-05-06
saadi torem lopez dupont

Cela me donne une erreur { inégalée.

# file1.txt (uid doens't match 8964)
admin: false
uid: 123456
happy
movie
DOB: 6543-02-10
lorem ipsum
seo varis lireccuni paccem noba sako

# file2.txt (uid matches 8964)
citizen: true
hasSEAcct: true
uid: 289641
joyful hearty
final debug Juno XYus
magazine
DOB: 1234-05-06
saadi torem lopez dupont


0 commentaires

3 Réponses :


2
votes
$ awk -v RS='' '/uid: [0-9]*8964/{sub(/DOB/, "FORBIDDEN\nDOB")} 1' file

3 commentaires

Merci de répondre. Ça marche vraiment. Cependant, je ne connais pas awk . Où puis-je apprendre les bases? Je ne peux trouver "drapeau" dans ce fameux awk tutoriel . Pourquoi FORBIDDEN est imprimé avant DOB et pas après ? J'ai essayé de remplacer 1 par 2 ou 0.5 à la ligne # 3 . Que signifie 1 ?


Ne soyez pas intimidé, c'est juste le niveau supérieur de Sed. Awk est également un outil pédagogique précieux pour la logique C , alors lisez man gawk . 1 (ou plus) est vrai, tandis que 0 (ou nul) est faux. «drapeau» n'est pas un terme officiel, juste l'idée d'une variable booléenne que nous activons ou désactivons pour garder un œil sur une condition. Lorsqu'il y a une condition sans {action} , comme 1 tout seul, awk effectue le comportement par défaut, qui est {print $ 0} ( imprimer toute la ligne).


Merci pour la réponse. J'ai parcouru man awk sur Ubuntu, et j'ai une meilleure idée de mawk . Si j'échange # 2 et # 3 , j'obtiens FORBIDDEN après DOB .



1
votes

À mon avis, c'est un bon cas d'utilisation de sed.

Voici une solution GNU sed avec quelques explications:

â–¶ gsed -e '/^uid:.*8964/,/DOB/{/DOB/i FORBIDDEN' -e '}' FILE*

Test: p >

â–¶ gsed -f script.sed FILE1
admin: false
uid: 123456
happy
movie
DOB: 6543-02-10
lorem ipsum
seo varis lireccuni paccem noba sako
â–¶ gsed -f script.sed FILE2 
citizen: true
hasSEAcct: true
uid: 289641
joyful hearty
final debug Juno XYus
magazine
FORBIDDEN
DOB: 1234-05-06
saadi torem lopez dupont

Ou sur une seule ligne:

# script.sed
/^uid:.*8964/,/DOB/ { # Search only inside this range, if it exists.
  /DOB/i FORBIDDEN    # Insert FORBIDDEN before the line matching /DOB/.
}


3 commentaires

Bonne réponse! En ce qui concerne la commande à une ligne, y a-t-il une raison à une telle séparation? Je sais seulement que si les trois expressions sont réunies, il y aura une erreur { inégalée.


@ GNUSupporter8964 民主 女神 地下 教會, et bonne question aussi au fait. Les multiples -e s sont là car la commande i s'attend à ce que des "lignes" de texte suivent. AFAIK, la chaîne à insérer doit être suivie d'un caractère de nouvelle ligne, mais le } doit encore fermer le bloc { .. } . Je ne connais donc pas d'autre moyen de tout mettre sur une seule ligne que d'utiliser plusieurs -e s.


Voir aussi les exemples ici gnu.org/software/sed/manual /sed.html#Other-Commands



1
votes

essayé sur gnu sed

 sed -Ee '/^uid:\s*\w*8964\w*$/{n;/^DOB:/iFORBIDDEN' -e '}' file*.txt


0 commentaires