2017-10-18 32 views
3

Je souhaite remplacer certaines lignes d'un fichier par des lignes d'un autre fichier basées sur la correspondance d'un motif. Je veux remplacer toutes les lignes qui commencent par "rolOccupant" après avoir trouvé "# SBD_ING_USER" à la ligne vide avec le contenu du fichier xComment puis-je remplacer des lignes d'un fichier texte par des lignes d'un autre fichier en fonction du motif correspondant?

fichier x

roleOccupant: uid1 
roleOccupant: uid2 
roleOccupant: uid45 
roleOccupant: uid80 

fichier d'entrée

# SDB_ING_USER 
objectClass: organizationalRole 
objectClass: top 
cn: SDB_ING_USER 
description: SDB Ing User Role 
roleOccupant: uid1 
roleOccupant: uid7 
roleOccupant: uid67 

# SDB_REGISTERY_USER: 
objectClass: organizationalRole 
objectClass: top 
cn: SDB_REGISTRY_USER 
description: SDB Registry Admin Role 
roleOccupant: uid2 
roleOccupant: uid34 
roleOccupant: uid15 

fichier de sortie

# SDB_ING_USER 
objectClass: organizationalRole 
objectClass: top 
cn: SDB_ING_USER 
description: SDB Ing User Role 
roleOccupant: uid1 
roleOccupant: uid2 
roleOccupant: uid45 
roleOccupant: uid80 

# SDB_REGISTERY_USER: 
objectClass: organizationalRole 
objectClass: top 
cn: SDB_REGISTRY_USER 
description: SDB Registry Admin Role 
roleOccupant: uid2 
roleOccupant: uid34 
roleOccupant: uid15 

Répondre

0

En utilisant awk

One-liner:

awk 'FNR==NR{r=(r!=""?r RS:"")$0;next}/# SDB_ING_USER/{u=1}u && /^roleOccupant:/{next}u && !NF{print r; u=""}1;END{if(u)print r}' file1 file2 

Mieux Lisible:

awk ' 
    FNR==NR{ 
      r=(r!=""?r RS:"")$0; 
      next 
    } 
    /# SDB_ING_USER/{ 
      u=1 
    } 
    u && /^roleOccupant:/{ 
     next 
    } 
    u && !NF{ 
     print r; 
     u="" 
    }1 
    END{ 
     if(u)print r 
    } 
    ' file1 file2 

Explication:

  • FNR==NR{r=(r!=""?r RS:"")$0;next} Ce bloc, nous lisons que file1 et sauvons fichier1 lignes variables r, séparés par le séparateur d'enregistrement RS, FNR==NR sera vrai, que lorsque awk lit premier fichier.

  • /# SDB_ING_USER/{u=1} si la ligne de file2, contient regexp dans /..../ puis, définir la variable u=1

  • u && /^roleOccupant:/{next} si la variable u est réglée, et la ligne commence par roleOccupant, sauter cette ligne, et passez à l'enregistrement suivant, de file2

  • u && !NF{print r; u=""} si la variable u est définie, et !NF, ce qui signifie ligne vide (NF donne pas de champs dans l'enregistrement, NF=0 moyens ligne vide, !0 est 1, ce qui est vrai état), puis imprimer la variable r, et annuler la variable u

  • }1 1 à la fin ne fonctionnement par défaut, thats impression d'enregistrement/ligne/ligne en cours, dans le contexte actuel , cette opération par défaut ne prend que si l'enregistrement n'est pas omis dans les instructions ci-dessus.

fichier_1:

$ cat file1 
roleOccupant: uid1 
roleOccupant: uid2 
roleOccupant: uid45 
roleOccupant: uid80 

file2:

$ cat file2 
# SDB_ING_USER 
objectClass: organizationalRole 
objectClass: top 
cn: SDB_ING_USER 
description: SDB Ing User Role 
roleOccupant: uid1 
roleOccupant: uid7 
roleOccupant: uid67 

# SDB_REGISTERY_USER: 
objectClass: organizationalRole 
objectClass: top 
cn: SDB_REGISTRY_USER 
description: SDB Registry Admin Role 
roleOccupant: uid2 
roleOccupant: uid34 
roleOccupant: uid15 

sortie:

$ awk 'FNR==NR{r=(r!=""?r RS:"")$0;next}/# SDB_ING_USER/{u=1}u && /^roleOccupant:/{next}u && !NF{print r; u=""}1;END{if(u)print r}' file1 file2 
# SDB_ING_USER 
objectClass: organizationalRole 
objectClass: top 
cn: SDB_ING_USER 
description: SDB Ing User Role 
roleOccupant: uid1 
roleOccupant: uid2 
roleOccupant: uid45 
roleOccupant: uid80 

# SDB_REGISTERY_USER: 
objectClass: organizationalRole 
objectClass: top 
cn: SDB_REGISTRY_USER 
description: SDB Registry Admin Role 
roleOccupant: uid2 
roleOccupant: uid34 
roleOccupant: uid15 
0

Lorsque le fichier d'entrée est sdb.txt et le fichier x est x.txt, j'utiliser un fichier de commandes sed cmd.sed pour ce faire:

sed -f cmd.sed sdb.txt

sed.cmd:

 
# Within the section from SDB_ING_USER to a blank line 
/SDB_ING_USER/,/^$/{ 
    # Delete roleOccupant lines 
    /roleOccupant/d 
    # At the blank line 
    /^$/{ 
     # Read x.txt into the output stream 
     r x.txt 
     # Append a blank line to the output stream 
     a 
     # Delete the blank line from the input stream 
     # (Prevents a blank line before the x.txt content) 
     d 
    } 
} 

Cela se fait avec une commande sed file plutôt que comme une seule ligne sed commande parce que les commandes sed r et a nécessitent un retour à la ligne, alors ils sont douloureux d'essayer d'utiliser dans un one-liner. (Voir ci-dessous concernant EDIT les nouvelles lignes et -e)

Sortie:

 
$ sed -f cmd.sed sdb.txt 
# SDB_ING_USER 
objectClass: organizationalRole 
objectClass: top 
cn: SDB_ING_USER 
description: SDB Ing User Role 
roleOccupant: uid1 
roleOccupant: uid2 
roleOccupant: uid45 
roleOccupant: uid80 

# SDB_REGISTERY_USER: 
objectClass: organizationalRole 
objectClass: top 
cn: SDB_REGISTRY_USER 
description: SDB Registry Admin Role 
roleOccupant: uid2 
roleOccupant: uid34 
roleOccupant: uid15 

EDIT. A vu l'utilisation de e cat de potong qui permet de lire le fichier x.txt dans l'espace de pattern (plutôt que le flux de sortie) ET réalisé que sur la ligne de commande vous pouvez utiliser plusieurs arguments -e pour obtenir des sauts de ligne efficaces dans les commandes sed one-liner.

Alors, voici un nouveau one-liner:

sed -e '/SDB_ING_USER/,/^$/{' -e '/roleOccupant/d' -e '/^$/e cat x.txt' -e '}' sdb.txt

2

awk one-liner

awk -v RS= -v ORS='\n\n' 'NR==FNR{a=$0;next} /SDB_ING_USER/{sub(/roleOccupant.*/,""); $0=$0 a} 1' fileX file 

-v RS= pour définir la ligne vide comme le dossier séparateur

FNR==NR{a=a$0; next}: Cette stockera votre contenu File X dans v ariable a

/# SDB_ING_USER/ {gsub(/roleOccupant.*/,a ORS)}: Alors que itérer sur votre Input file si l'enregistrement contient # SDB_ING_USER alors de remplacer toutes les lignes à partir de roleOccupant à la fin du record avec a ORS autrement dit a "\n"

Sortie:

# SDB_ING_USER 
objectClass: organizationalRole 
objectClass: top 
cn: SDB_ING_USER 
description: SDB Ing User Role 
roleOccupant: uid1 
roleOccupant: uid2 
roleOccupant: uid45 
roleOccupant: uid80 

# SDB_REGISTERY_USER: 
objectClass: organizationalRole 
objectClass: top 
cn: SDB_REGISTRY_USER 
description: SDB Registry Admin Role 
roleOccupant: uid2 
roleOccupant: uid34 
roleOccupant: uid15 
0

Cette pourrait fonctionner pour vous (GNU sed):

sed '/SDB_ING_USER/,/^\s*$/!b;/roleOccupant/d;/^\s*$/e cat x' file 

Concentrez-vous sur les lignes entre SDB_ING_USER et la ligne vide suivante.Supprimez toutes les lignes contenant la chaîne roleOccupant et insérez le fichier x avant la ligne vide.

+0

Merci :) ça marche – MBA