Insérer un retour chariot après chaque occurence grep

Résolu/Fermé
xavnug - Modifié le 29 nov. 2022 à 09:59
mamiemando Messages postés 32948 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 22 février 2024 - 29 nov. 2022 à 10:49

Bonjour à tous,

Après de longues recherches, je ne trouve pas réponse à mon problème.

Je dispose d'un fichier texte qui ressemble à ça :

id : xxxxxxxxx
name : xxxxxxxxxxxx
id : xxxxxxxxx
name : xxxxxxxxxxxx
id : xxxxxxxxx
name : xxxxxxxxxxxx

Je cherche à capturer toutes les lignes où l’occurrence "id" apparaît et à les envoyer vers un autre fichier texte (sans modifier le fichier existant) en insérant un retour chariot entre chaque occurrence.

Je sais capturer les occurrences :

grep -E "id" fichier1 > fichier2

... mais je bloque sur l'insertion du retour charriot ...

Merci d'avance pour votre aide


Windows / Firefox 107.0

A voir également:

8 réponses

dubcek Messages postés 18711 Date d'inscription lundi 15 janvier 2007 Statut Contributeur Dernière intervention 24 février 2024 5 612
Modifié le 26 nov. 2022 à 15:28

hello

$ awk '/id/ {print $0  "\n"}' fichier
id : xxxxxxxxx

id : xxxxxxxxx

id : xxxxxxxxx

1
dubcek Messages postés 18711 Date d'inscription lundi 15 janvier 2007 Statut Contributeur Dernière intervention 24 février 2024 5 612
27 nov. 2022 à 12:02
$ awk '/id|name/ {print $0} /name/ {print ""}' fichier
id : azerty
name : qsdfg

id : poiuy
name : mlkjh

$ 

essayer  cours awk dans Google

1

Merci beaucoup dubcek !

Du coup j'ai plusieurs questions :

  1. Si je comprends bien dans ta réponse, tu "captures" avec awk les lignes contenant "id" puis tu insères une ligne entre chaque occurrence avec {print $0 "\n"} ?
  2. Dans le print, quelle est le rôle de $0 ?
  3. Si je veux appliquer la même logique à plusieurs lignes, par exemple :
id : azerty
name : qsdfg
adresse : wxcvb

id : poiuy
name : mlkjh
adresse : nbvcx

... j'arrive bien à "capturer" les lignes contenant "id" et "name".

Mais lorsque je les envoie dans un autre fichier avec :

awk '/"id"|"name"/ {print $0 "\n"}' auth >authentifications.txt

....j'obtiens ceci :

id : azerty
name : qsdfg
id : poiuy
name : mlkjh

Je ne sais pas trop comment faire ...

Ou sinon un bon cours grep / sed / awk à me proposer ?

D'avance merci

0

je me réponds à ma moi-même pour le $0, je viens de trouver : c'est demander à awk l'entière ligne d'un texte, dans mon cas la ligne où se trouve "id" ...

par contre pour le reste je bloque ...

0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
dubcek Messages postés 18711 Date d'inscription lundi 15 janvier 2007 Statut Contributeur Dernière intervention 24 février 2024 5 612
27 nov. 2022 à 10:36

$0 c'est toute la ligne, $n c'est  le champ n

c'est ça que tu veux ?

id : azerty
name : qsdfg

id : poiuy
name : mlkjh
0

c'est ça oui

0

Merci beaucoup pour le coup de main

0
mamiemando Messages postés 32948 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 22 février 2024 7 722
29 nov. 2022 à 10:49

Hello xavnug

Petit cours express de awk. 

  • Le nom de awk vient de ses concepteurs (Alfred Aho, Peter Weinberger et Brian Kernighan)
  • awk peut s'utiliser en passant un paramètre un fichier qui contient les instructions ou en passant directement les instructions en paramètre comme le fait dubcek. Quand les instructions sont simples c'est souvent cette seconde approche qui est adoptée car cela évite d'avoir à créer un fichier. Quand cela devient plus compliqué on passe par un fichier (e.g., awk -f script.awk fichier.txt)
  • Un script awk part du principe qu'on lit un fichier token par token (par défaut un token est une ligne de texte). À chaque ligne lue, on applique la ou les règles qui s'appliquent dans le script awk.
  • Les règles sont appliquées (ou non) dans l'ordre de leur déclaration dans le script (de haut en bas).
  • Chaque règle est composé d'un test (avant la paire d'accolade) et d'une action (dans la paire d'accolade qui suit le test). Parmi les tests possibles il y a :
    • BEGIN : bloc évalué au lancement du script, quand on lit la première ligne (souvent utilisé pour initialiser les variables globales du script awk)
    • END : bloc évalué à la sortie du script (souvent pour utilisé pour écrire les valeurs de variables globales en fin de script)
    • Les autres : évalués à chaque fois qu'une ligne de texte est découverte. Il existe plein de tests envisageables, mais le plus souvent on compare la ligne courante $0 avec une expression régulière. En awk une expression régulière. Cela s'écrit $0 ~ /regexp/ ou abrégé /regexp/ regexp est une expression regulière.
  • L'action associée à une règle ressemble à du code écrit en C simplifié (contrairement au C, les variables sont non typées et il n'y a pas à gérer la mémoire). Les primitives supportées et la syntaxe sont spécifiées dans man awk. Ces instructions se basent souvent sur le résultat de variables mises à jours dynamiquement par awk en fonction de la ligne en cours de traitement ($0 = la ligne courante, $i la ligne = le ième champ de la ligne courante) et quelques autres (NR, NF, etc, voir man awk). Les champs d'une ligne sont obtenus conformément à un séparateur (par défaut, une suite non vide d'espace) mais c'est également personnalisable.
  • Pour chacune lig

Si on réécrit le script proposé par dubcek sous forme de fichier on obtient :

script.awk

/id|name/ {
  print $0;
}

/name/ {
  print "";
}

On voit donc clairement deux règles :

  1. La première (équivalente à $0 ~ /id|name/) signifie que la ligne courante est comparée à l'expression rationnelle qui teste si la sous-chaîne "id" ou la sous-chaîne "name" est présente. Si c'est le cas, on réécrit la ligne courante (print $0). Implicitement, un print en awk passe à la ligne.
  2. La seconde (équivalente à $0 ~ /name/) signifie la ligne courante est comparée à l'expression rationnelle qui teste si la sous-chaîne"name" est présente. Si c'est le cas, on réécrit la ligne courante (print $0). Si c'est le cas on écrit la chaîne vide, et le passage à la ligne implicite fait le reste.

Donc :

  • Si on lit une chaîne qui contient "id", seule la première règle est appliquée.
  • Si on lit une ligne qui contient "name" on applique la première règle puis la seconde.
  • Sinon aucune règle ne s'applique (et la ligne courante est donc ignorée)

À noter que le script en l'état est un peu laxiste, car si une ligne contient par exemple "id : my_name" alors la deuxième règle s'applique. Même limitation sur une ligne qui contient "pouet : id". Donc on écrirait plutôt :

fichier.txt

id : azerty
name : qsdfg id
pouet : name id

id : poiuy
name : mlkjh

script.awk

/^(id|name)( |\t)*:/ {
  print $0;
}

/^name( |\t)*:/ {
  print "";
}

Les expressions régulières (aussi appelées expressions rationnelles) sont, comme leur nom le suggère, une manière de caractériser un langage régulier (aussi appelé langage rationnel) à l'aide d'une chaîne de caractère. Cette chaîne de caractère implique des symboles (les caractères de l'alphabet considéré) et des métacaractères (les opérateurs des expressions régulières).

Si dans une expression régulière on veut parler d'un symbole qui correspond à un métacaractère il faut donc l'échapper. Par exemple, comme * est un méta caractère, le symbole correspondant s'écrit \* ou [*].

Toute la syntaxe des expressions régulières est rappelée dans man awk.

Voyons à présent les expressions régulières du script précédent.

  • ^ est le méta caractère qui signifie "commence par"
  • | est le méta caractère qui signifie "ou bien"
  • (id|name) signifie que l'on attend la suite de caractère "id" ou bien la suite de caractère "name". Note que les parenthèses sont elles-mêmes des méta caractères.
  • ( |\t) signifie soit le caractère espace, soit le caractère tabulation.
  • * est le méta caractère qui signifie que le langage qui précède cet opérateur (ici le langage défini ( |\t)) peut être répété n fois avec n >= 0. Cet opérateur s'appelle l'étoile de Kleene.
  • : signifie qu'on attend le caractère ":"

Si on teste ce script :

awk -f script.awk fichier.txt

 ... on obtient alors :

id : azerty
name : qsdfg id

id : poiuy
name : mlkjh

Bonne chance

0