Función de escape seguro para salida de terminal
Pregunta
Estoy buscando el equivalente de un urlencode para salida de terminal: necesito asegurarme de que los caracteres basura que (puedo) imprimir desde una fuente externa no terminen haciendo cosas extrañas en mi terminal, por lo que una función preempaquetada para escapar de secuencias de caracteres especiales sería ideal.
Estoy trabajando en Python, pero cualquier cosa que pueda traducir fácilmente también funciona. TIA!
Solución
$ ./command | cat -v $ cat --help | grep nonprinting -v, --show-nonprinting use ^ and M- notation, except for LFD and TAB
Esto es lo mismo en py3k basado en android / cat.c :
#!/usr/bin/env python3
"""Emulate `cat -v` behaviour.
use ^ and M- notation, except for LFD and TAB
NOTE: python exits on ^Z in stdin on Windows
NOTE: newlines handling skewed towards interactive terminal.
Particularly, applying the conversion twice might *not* be a no-op
"""
import fileinput, sys
def escape(bytes):
for b in bytes:
assert 0 <= b < 0x100
if b in (0x09, 0x0a): # '\t\n'
yield b
continue
if b > 0x7f: # not ascii
yield 0x4d # 'M'
yield 0x2d # '-'
b &= 0x7f
if b < 0x20: # control char
yield 0x5e # '^'
b |= 0x40
elif b == 0x7f:
yield 0x5e # '^'
yield 0x3f # '?'
continue
yield b
if __name__ == '__main__':
write_bytes = sys.stdout.buffer.write
for bytes in fileinput.input(mode="rb"):
write_bytes(escape(bytes))
Ejemplo:
$ perl -e"print map chr,0..0xff" > bytes.bin $ cat -v bytes.bin > cat-v.out $ python30 cat-v.py bytes.bin > python.out $ diff -s cat-v.out python.out
Imprime:
Files cat-v.out and python.out are identical
Otros consejos
Desafortunadamente " salida de terminal " es un criterio muy poco definido para el filtrado (consulte pregunta 418176 ) Sugeriría simplemente incluir en la lista blanca los caracteres que desea permitir (que sería la mayor parte de string.printable), y reemplazar todos los demás con el formato de escape que desee (\ FF,% FF, etc.), o incluso simplemente eliminarlos.
Si registro o imprimo resultados de depuración, generalmente uso repr ()
para obtener una versión imprimible inofensiva de un objeto, incluidas las cadenas. Esto puede o no ser lo que querías; El método cat --show-nonprinting
que otros han usado en otras respuestas es mejor para muchas salidas de varias líneas.
x = get_weird_data()
print repr(x)
Podrías canalizarlo a través de cadenas
./command | strings
Esto eliminará los caracteres que no sean cadenas