1
votes

Supprimer uniquement le premier saut de ligne

J'ai pas mal de fichiers dans lesquels je souhaite supprimer un saut de ligne particulier. La ligne commence toujours par "Title:" et j'ai donc essayé la commande suivante:

find . -type f -exec sed -i 's/^Title: \n\t*/Title:/g' {} \;

Mais d'après ce que j'ai compris, sed ne gère qu'une ligne à la fois, et donc ce qui précède ne fonctionnera pas. Existe-t-il un moyen de supprimer un saut de ligne (dans plusieurs fichiers), mais uniquement si la ligne commence par une chaîne?


3 commentaires

La ligne commence par "Title:" ou est-ce la ligne entière ? Dans votre tentative, la ligne entière se compose exactement de "Titre:" suivi d'un espace et rien d'autre . Précisez s'il vous plaît. De plus, vous n'avez pas mentionné la suppression des onglets, mais votre tentative recherche zéro ou plusieurs onglets après la nouvelle ligne; c'est quoi ça? Si vous avez besoin de gérer ces onglets, dites-le dans votre question textuelle, pas seulement dans le code.


Encore quelques questions: Pouvez-vous avoir deux lignes consécutives commençant par "Titre:"? La dernière ligne de tout votre truc peut-elle commencer par "Titre:"? Si oui, dans les deux cas, quelle est la manipulation souhaitée?


@mathguy J'ai simplifié l'expression régulière ci-dessus pour la rendre un peu plus compréhensible et pour montrer l'idée principale. C'est pourquoi j'ai dit "commence par" ci-dessus. Et non, c'est généralement l'une des 10 premières lignes du fichier qui commence par "Titre"


3 Réponses :


1
votes

Avec GNU sed , vous pouvez utiliser

sed '/^Title: $/{N;s/.*\n\t*\(.*\)/Title:\1/}'

Voir le démo sed en ligne

  • / ^ Title: $ / - trouve une ligne dont le contenu est égal à Title:
  • {N; s /.* \ n \ t * \ (. * \) / Title: \ 1 /} - un bloc exécuté une fois que la ligne ci-dessus est trouvée:
    • N - obtient la ligne suivante et ajoute une nouvelle ligne et cette ligne à l'espace du motif
    • s /.* \ n \ t * \ (. * \) / Title: \ 1 / - remplace l'espace de motif (qui contient maintenant deux lignes) en utilisant le . * \ n \ t * \ (. * \) qui correspond
      • . * - 0 ou plus de caractères
      • \ n \ t * - une nouvelle ligne et plus de 0 onglets
      • \ (. * \) - Groupe de capture 1: 0 ou plus de caractères
      • / Title: \ 1 / - modèle de remplacement, Title: et la valeur à l'intérieur du groupe 1.


6 commentaires

L'indicateur -E manque? Je pense que les groupes de capture et les références en arrière l'exigent.


Non, c'est une expression BRE POSIX.


Dans un sed BSD gratuit, essayez sed -e '/ ^ Title: $ / {' -e N -e 's /.* \ n \ t * \ (. * \) / Title: \ 1 /' -e '}'


Oh, d'accord, d'accord. Ma mémoire me fait défaut - j'ai lu le standard POSIX une fois, et je pensais savoir ce qu'est BRE et ce qu'est ERE, mais il y a clairement des bugs dans ma mémoire. Merci!


Pourquoi n'avez-vous pas besoin de fermer avec un / à la fin? Alors pourquoi est-ce faux: sed '/ ^ Title: $ / {N; s /.* \ n \ t * \ (. * \) / Title: \ 1 /} /' ?


Il ne devrait pas y avoir de / à la fin, il y a un bloc.



0
votes

Je le ferais comme ceci:

sed '/^Title:/{N;s/[[:blank:]]*\n[[:blank:]]*/ /}'

Ceci recherchera toute ligne commençant par la chaîne "Titre:". Il ajoutera une nouvelle ligne et la ligne suivante dans l'entrée. Ensuite, il recherchera un caractère de nouvelle ligne, éventuellement précédé et / ou suivi par n'importe quel nombre (zéro ou plus) de caractères vides - signifiant un espace ou une tabulation - et il remplacera tout cela par un seul espace.

Cela suppose que la ligne "Titre:" peut également inclure un autre texte (sur la même ligne) et qu'il doit être conservé. C'est ma compréhension de votre question, d'après ce que vous avez dit en mots (cela ne correspond pas à votre tentative cependant).

Vous devrez peut-être un traitement spécial si votre entrée peut contenir deux lignes consécutives commençant par "Titre : "(cette solution les joindra en une seule ligne), et si la toute dernière ligne commence par" Titre: "(cette solution la laissera tranquille - à moins, bien sûr, que la ligne juste au-dessus ne commence également par" Titre : ").


0 commentaires

0
votes

Cela pourrait fonctionner pour vous (GNU sed):

sed -Ez ':a;s/((^|\n)Title:) \n\t*/\1/g;ta' file

Glissez le fichier dans la mémoire en utilisant -z option.

Autoriser une expression régulière étendue en utilisant le - Option E .

Si la première ligne ou une ligne suivante commence par Title: suivi d'une nouvelle ligne et de zéro ou plusieurs onglets, supprimez le trio d'un espace suivi de retour à la ligne suivi de zéro ou plusieurs onglets.

Cela peut réduire le fichier dans un autre état correspondant, donc une boucle peut être nécessaire:

sed -Ez 's/((^|\n)Title:) \n\t*/\1/g' file


0 commentaires