Je cherche un moyen d'exécuter le remplacement uniquement lorsque le dernier caractère est une nouvelle ligne, en utilisant sed
.
Par exemple:
lettersAtEndOfLine
est remplacé, mais ce n'est pas:
lettersWithCharacterAfter&
Puisque sed
ne fonctionne pas bien avec les sauts de ligne, ce n'est pas aussi simple que
$ sed -E "s/[a-zA-Z]*\n/replace/" file.txt
Comment cela peut-il être accompli?
Avec la norme sed
, vous jamais verrez une nouvelle ligne dans le texte lu à partir d'un fichier. Cela est dû au fait que sed
lit ligne par ligne, et il n'y a donc pas de nouvelle ligne à la fin du texte de la ligne actuelle dans l'espace modèle de sed
. En d'autres termes, sed
lit les données délimitées par des sauts de ligne et les délimiteurs ne font pas partie de ce que voit un script sed
.
Les expressions régulières peuvent être ancrées à la fin de la ligne en utilisant $
(ou au début, en utilisant ^
). L'ancrage d'une expression au début/à la fin d'une ligne la force à correspondre exactement là, et pas seulement n'importe où sur la ligne.
Si vous souhaitez remplacer tout ce qui correspond au modèle [A-Za-z]*
à la fin de la ligne avec quelque chose, puis ancrer le motif comme ceci:
[A-Za-z]*$
... le forcera à correspondre à la fin de la ligne et nulle part ailleurs.
Cependant, puisque [A-Za-z]*$
correspond également à rien (par exemple, la chaîne vide présente à la fin de chaque ligne), vous devez forcer la correspondance de quelque chose , par exemple en spécifiant
[A-Za-z][A-Za-z]*$
ou
[A-Za-z]\{1,\}$
Ainsi, votre ligne de commande sed sera donc
$ sed 's/[A-Za-z]\{1,\}$/replace/' file.txt
Je n'ai pas utilisé le -E
basculez ici car ce n'est pas nécessaire. Avec ça, vous auriez pu écrire
$ sed -E 's/[A-Za-z]+$/replace/' file.txt
C'est une question de goût.
sed "s/[a-zA-Z]*$/replace/" input.txt > result.txt
Ou, la manière inutile longue et complexe:
J'ai découvert que cela peut être fait, en utilisant toujours sed, avec l'aide de tr. Vous pouvez attribuer un autre caractère pour représenter la fin de la ligne. Un autre caractère temporaire doit être utilisé, dans ce cas "" ". Utilisons "~" pour représenter la fin de la ligne:
tr '\n' '`' <input.txt >output.txt sed -i "s/`/~`/" output.txt tr '`' '\n' <output.txt >result.txt
Et puis pour effectuer la recherche réelle et remplacer, utilisez "~" plutôt que "\ n":
sed -i -E "s/[a-zA-Z]*~/replace/" result.txt
Et puis nettoyez le caractère supplémentaire sur les autres lignes:
sed -i "s/~//" result.txt
De toute évidence, tout cela peut être canalisé, ce qui donne quelque chose comme:
tr '\n' '`' <input.txt | sed -e "s/`/~`/" | tr '`' '\n' | sed -E -e "s/[a-zA-Z]*~/replace/" | sed "s/~//" > result.txt
Pour trouver la fin de la ligne, utilisez simplement le signe $ -:
Sans ancrage de fin de ligne:
sed -n '/pattern/p' file
Sans ancrage de fin de ligne:
sed -n '/pattern$/p' file
À partir de l'extrait de code (cassé) que vous avez publié, vous semblez également vouloir remplacer la nouvelle ligne. Dans ce cas, l'ancrage regex par lui-même ne peut pas vous aider. Voici une solution:
sed '/[[:alpha:]]\+$/{N;s/[[:alpha:]]\+\n/replace/}' your_file
En panne:
/[a-zA-Z]\+$/{}
signifie appliquer tout ce qui se trouve à l'intérieur des boucles aux lignes qui correspondent à l'expression régulière.N
signifie "ajouter la ligne suivante au tampon actif" (ce que sed
appelle "l'espace modèle")s///
l'instruction est votre substitution requise. Cela fonctionne maintenant car l'espace de motif contient deux lignes successives et la nouvelle ligne en fait donc partie.