Vous pouvez le faire avec vim
stdin
et stdout
. Vous pouvez également utiliser ex
pour être conforme à POSIX . vim
est juste le mode visuel pour ex
. En fait, vous pouvez utiliser ex
avec vim -e
ou vim -E
( ex
mode amélioré ).
vim
est utile parce que contrairement à des outils comme sed
celui-ci, le fichier sed
est mis en mémoire tampon pour l'édition, tandis que est utilisé pour les flux. Vous pourrez peut-être utiliser awk
, mais vous devrez tout mettre manuellement en mémoire tampon dans une variable.
L'idée est de faire ce qui suit:
- Lire depuis stdin
- Pour chaque ligne, déplacez-le sur la ligne 1 (pour inverser). Le commandement est
g/^/m0
. Cela signifie globalement, pour chaque ligne g
; correspond au début de la ligne, qui correspond à tout ^
; déplacez-le après l'adresse 0, qui est la ligne 1m0
.
- Imprimez tout. Le commandement est
%p
. Cela signifie pour la gamme de toutes les lignes %
; imprimer la ligne p
.
- Quittez de force sans enregistrer le fichier. Le commandement est
q!
. Cela signifie quitter q
; avec force !
.
# Generate a newline delimited sequence of 1 to 10
$ seq 10
1
2
3
4
5
6
7
8
9
10
# Use - to read from stdin.
# vim has a delay and annoying 'Vim: Reading from stdin...' output
# if you use - to read from stdin. Use --not-a-term to hide output.
# --not-a-term requires vim 8.0.1308 (Nov 2017)
# Use -E for improved ex mode. -e would work here too since I'm not
# using any improved ex mode features.
# each of the commands I explained above are specified with a + sign
# and are run sequentially.
$ seq 10 | vim - --not-a-term -Es +'g/^/m0' +'%p' +'q!'
10
9
8
7
6
5
4
3
2
1
# non improved ex mode works here too, -e.
$ seq 10 | vim - --not-a-term -es +'g/^/m0' +'%p' +'q!'
# If you don't have --not-a-term, use /dev/stdin
seq 10 | vim -E +'g/^/m0' +'%p' +'q!' /dev/stdin
# POSIX compliant (maybe)
# POSIX compliant ex doesn't allow using + sign to specify commands.
# It also might not allow running multiple commands sequentially.
# The docs say "Implementations may support more than a single -c"
# If yours does support multiple -c
$ seq 10 | ex -c "execute -c 'g/^/m0' -c '%p' -c 'q!' /dev/stdin
# If not, you can chain them with the bar, |. This is same as shell
# piping. It's more like shell semi-colon, ;.
# The g command consumes the |, so you can use execute to prevent that.
# Not sure if execute and | is POSIX compliant.
seq 10 | ex -c "execute 'g/^/m0' | %p | q!" /dev/stdin
Comment rendre cela réutilisable
J'utilise un script que j'appelle ved
(comme l'éditeur vim sed
) pour utiliser vim pour éditer stdin
. Ajoutez ceci à un fichier appelé ved
dans votre chemin:
#!/usr/bin/env sh
vim - --not-a-term -Es "$@" +'%p | q!'
J'utilise une +
commande au lieu de +'%p' +'q!'
, car vim vous limite à 10 commandes. Leur fusion permet donc "$@"
d'avoir 9+
commandes au lieu de 8.
Ensuite, vous pouvez faire:
seq 10 | ved +'g/^/m0'
Si vous n'avez pas vim 8, mettez-le à la ved
place:
#!/usr/bin/env sh
vim -E "$@" +'%p | q!' /dev/stdin
perl -e 'print reverse <>'
mais cela s'applique probablement aussi à d'autres méthodes).