GNU/Linux >> Tutoriels Linux >  >> Linux

Dupliquer, avec quelques petites modifications, quelques lignes dans un fichier texte ?

J'essaie de trouver comment répliquer une seule plage de lignes dans un fichier texte. La plage commence par une ligne unique dans le fichier, mais la plage se termine par une ligne qui peut exister à plusieurs endroits dans le fichier.

Voici quelques exemples d'entrée que je dois traiter :

I have no imagination
so this sample text will
Common
be boring. But it does
demonstrate the problem
I am trying to solve.
Common
Hi mom!
This is a unique line.
And here is some more
text that should be copied
as well.
Common
Followed by text that should
not be copied.

Les lignes que je dois dupliquer et modifier sont en gras pour les signaler ici.

La sortie dont j'ai besoin est :

I have no imagination
so this sample text will
Common
be boring. But it does
demonstrate the problem
I am trying to solve.
Common
Hi mom!
This is a changed line.
And here is different more
text that should be copied
as well.
Common
This is a unique line.
And here is some more
text that should be copied
as well.
Common
Followed by text that should
not be copied.

La sortie supplémentaire est en gras pour le rendre clair.

J'ai besoin d'obtenir la plage de lignes commençant par la ligne :

This is a unique line

et se terminant par la ligne :

Common

Cette plage de lignes doit être insérée juste avant la plage de lignes d'origine. La copie de la plage de lignes correspondante devra être légèrement modifiée.

La ligne "Common" qui termine la plage peut elle-même apparaître à de nombreux endroits dans le fichier.

Je suis venu avec un awk fonctionnel script, mais cela semble beaucoup plus compliqué que nécessaire. Mon awk les compétences sont inexistantes.

/This is a unique line/{flag=1}
/Common/{
    if (flag > 0) {
        n=m;
        sub("some","different",n);
        sub("unique","changed",n);
        print n "\n" $0 "\n" m;
        m=""
    };
    flag=0
};
flag{
    if (length(m) > 0) {
        m=m "\n" $0
    } else {
        m=$0
    }
}
!flag{ print }

Existe-t-il un moyen plus propre et moins verbeux d'implémenter cela? Je suis ouvert à d'autres options que awk . Il doit simplement s'agir d'une commande standard disponible sur macOS.

Réponse acceptée :

awk '/This is a unique line/,/Common/{
   H = H RS $0
   if ( $0 ~ /Common/ ) {
      g = H
      sub("\n","",g)
      sub("some","different",g)
      sub("unique","changed",g)
      $0 = g H
   } else { next }
}1'   inputfile

Voici le sed code (j'ai montré dans la section Réponse) traduit en awk .

Notez que, le code que vous avez, vous prenez la responsabilité d'activer/désactiver le awk drapeau variable pour garder une trace des lignes. Mais alors que, awk le fait déjà pour vous sous le capot exactement la même chose lorsque vous utilisez sa range opérateur ,


Linux
  1. Cat ligne X à ligne Y sur un énorme fichier ?

  2. Comment supprimer les lignes en double dans un fichier texte ?

  3. Insérer de nouvelles lignes avec des valeurs manquantes (na) ?

  4. Supprimer efficacement les premières lignes d'un fichier texte ?

  5. Supprimer des lignes consécutives dans Csv avec des valeurs en double dans un champ, mais conserver la dernière ligne ?

Commande Diff sous Linux avec exemples

Manipulation de texte en ligne de commande avec sed

Manipuler du texte en ligne de commande avec grep

Comment trouver la ou les lignes les plus longues dans un fichier sous Linux

Comment ajouter plusieurs lignes à un fichier ?

Suivre les modifications de Crontab avec Git ?