Puedes hacerlo con vim stdiny stdout. También puede usar expara cumplir con POSIX . vimes solo el modo visual para ex. De hecho, puede usar excon vim -eo vim -E( exmodo mejorado ).
vimes útil porque, a diferencia de herramientas como sedesta, almacena el archivo para editarlo, mientras que sedse usa para transmisiones. Es posible que pueda usar awk, pero tendría que almacenar manualmente todo en una variable.
La idea es hacer lo siguiente:
- Leer de stdin
- Para cada línea muévala a la línea 1 (para invertir). Comando es
g/^/m0. Esto significa globalmente, para cada línea g; coincide con el inicio de la línea, que coincide con cualquier cosa ^; muévalo después de la dirección 0, que es la línea 1 m0.
- Imprime todo. Comando es
%p. Esto significa para el rango de todas las líneas %; imprime la línea p.
- Salga con fuerza sin guardar el archivo. Comando es
q!. Esto significa dejar de fumar q; enérgicamente !.
# 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
Cómo hacer que esto sea reutilizable
Uso un script que llamo ved(editor de vim sed) para usar vim para editar stdin. Agregue esto a un archivo llamado veden su ruta:
#!/usr/bin/env sh
vim - --not-a-term -Es "$@" +'%p | q!'
Estoy usando un +comando en lugar de +'%p' +'q!', porque vim te limita a 10 comandos. Por lo tanto, fusionarlos le permite "$@"tener 9 +comandos en lugar de 8.
Entonces puedes hacer:
seq 10 | ved +'g/^/m0'
Si no tienes vim 8, pon esto en su vedlugar:
#!/usr/bin/env sh
vim -E "$@" +'%p | q!' /dev/stdin
perl -e 'print reverse <>'pero probablemente también se aplica a otros métodos).