Suppression de l'avant-dernier caractère de chaque ligne – avec sed

Comment supprimer le caractère avant le dernier caractère de chaque ligne d'un file?

J'ai essayé sed 's/.$//' myfile1.txt qui a enlevé le dernier caractère de chaque ligne dans myfile1.txt , mais je ne suis pas sûr de savoir comment supprimer l'avant-dernier caractère de chaque ligne.

Tu peux faire:

 sed -E 's/.(.)$/\1/' file.txt 

Pour modifier le file en place, sans sauvegarde:

 sed -Ei 's/.(.)$/\1/' file.txt 

Pour modifier le file en place, avec le file d'origine sauvegardé avec l'extension .bak :

 sed -Ei.bak 's/.(.)$/\1/' file.txt 

POSIX-ly:

 sed 's/.\(.\)$/\1/' file.txt 

Pour expliquer en détail la command portable (puisque quelqu'un a demandé) afin que tout le monde puisse comprendre ceci:

 sed 's/.\(.\)$/\1/' file.txt 

Tout d'abord, le "évident": Cette ligne se compose d'un nom de command ( sed ) et de deux arguments distincts qui sont passés à cette command par le shell. Les guillemets simples sont dépouillés par le shell, donc ce sed "voit" comme ses arguments sont:

s/.\(.\)$/\1/

et

file.txt

Puisque aucun des arguments de sed commence par un trait d'union, il n'interprète aucune d'entre elles comme des options.

Le premier argument est interprété comme une command d'édition à exécuter et tout autre argument (dans ce cas, le seul, file.txt ) est interprété comme le nom des files à partir desquels lire le text à modifier par la command d'édition premier argument).

(Notez que le text édité est écrit dans la "sortie standard" de sed – c'est-à-dire, de return à votre terminal, votre window de command line – il n'est pas réécrit dans le file.)

file.txt doit être un nom de file d'un file situé dans le directory qui est le «directory de travail courant» de votre shell lorsque vous exécutez cette command sed . (Si vous voulez que la command fonctionne sur le même file quel que soit le directory de travail actuel de votre shell lorsque vous exécutez la command, lisez les "paths absolus".)


Nous allons maintenant débuild la command d'édition elle-même:

s/.\(.\)$/\1/

La command d'édition commence par la lettre s , qui est pour "substitut". Du caractère qui suit le "s" (qui est / dans ce cas), jusqu'à la prochaine instance de ce même caractère ( / encore), est le motif qui doit être substitué. En d'autres termes, il spécifie à quoi doit ressembler le text qui doit être remplacé – il indique à sed comment "savoir" quand il a trouvé du text qui devrait être remplacé (devrait être remplacé).

Le model dans ce cas est:

.\(.\)$

(Le terme approprié à la place de «pattern» est en réalité regex , à l'origine abréviation de «regular expression». Je n'entrerai pas ici dans le sujet plus large des regexes.)

Cette regex commence par un point ( . ), Qui est un "caractère générique" avec la signification "un seul caractère". Il correspond (décrit, symbolise) tout caractère unique du text.

La barre oblique inverse ( \ ) est souvent utilisée dans les commands shell et les regexes comme caractère "escape". En général, cela signifie que soit il supprime la signification spéciale du caractère qui le suit, soit il ajoute une signification spéciale au caractère suivant.

Dans ce cas, les parenthèses (les deux ( et ) ) sont échappées (c'est-à-dire précédées d'une barre oblique inverse) afin d' append un sens spécial. La signification spéciale des parenthèses échappées dans une regex sed est que tout text qui correspond à la partie de l'expression entre les parenthèses est "notée" spécialement et peut être renvoyé à. Nous y reviendrons plus tard (quand nous nous référons à ce groupe de parenthèses).

La période ( . ) Entre les parenthèses correspond à nouveau à un seul caractère.

Le signe dollar ( $ ) est appelé ancre et correspond à la fin d'une ligne de text. En l'absence de cette ancre, l'expression rationnelle correspondrait simplement à deux caractères (en particulier, elle correspondrait aux deux premiers caractères de chaque ligne de text lue dans le file file.txt ) et (en raison des parenthèses échappées) sed " note "le deuxième des deux caractères pour se référer à plus tard.

Comme l'expression rationnelle est ancrée à la fin de la ligne, les deux points doivent correspondre aux deux derniers caractères de chaque ligne de text (et le caractère final est noté pour reference ultérieure).

La partie suivante de la command s (substitute) provient de la seconde instance du caractère suivant s (dans ce cas une barre oblique, / ), à la troisième instance du caractère suivant s . C'est ce qu'on appelle le model de rlocation. Il spécifie ce que sed devrait mettre en place du text correspondant au model de search (l'expression rationnelle).

Dans ce cas, le model de rlocation est:

\1

Encore une fois, la barre oblique inverse est utilisée pour échapper au caractère suivant, et dans ce cas, il est encore une fois d' append un sens spécial plutôt que d'enlever un sens spécial.

Une barre oblique inverse suivie d'un chiffre (de 1 à 9) s'appelle une reference arrière. C'est ce qui renvoie au text apparié entre parenthèses regroupant dans le model de search. Puisque le chiffre est 1 , cela fait reference au groupement des premières parenthèses. (Dans ce cas, bien sûr, il n'y en a qu'un seul.)

En résumé, cette command d'édition permet d'utiliser le text apparié à l'intérieur de ces parenthèses échappées (qui est le caractère final de la ligne) pour replace le text correspondant à toute l' expression rationnelle de search (qui représente les deux derniers caractères de la ligne).

L'effet net est de supprimer l'avant dernier caractère de chaque ligne.

Ou, plus précisément, sed lit dans chaque ligne de text à partir du file appelé file.txt trouvé dans le directory de travail en cours; pour chaque ligne, il replacea les deux derniers caractères de la ligne par le caractère final unique de cette ligne; et il imprimera chaque ligne modifiée à sa sortie standard.