Tengo un montón de archivos txt, me gustaría mostrarlos en minúsculas, solo alfabéticos y una palabra por línea, puedo hacerlo con varios tr
comandos en una tubería como esta:
tr -d '[:punct:]' <doyle_sherlock_holmes.txt | tr '[:upper:]' '[:lower:]' | tr ' ' '\n'
¿Es posible hacer esto en un escaneo? Podría escribir un programa en C para hacer esto, pero me siento como si hubiera una manera de hacerlo utilizando tr
, sed
, awk
o perl
.
Respuestas:
Puede combinar varias traducciones (excepto casos complejos que involucran conjuntos superpuestos dependientes de la configuración regional), pero no puede combinar la eliminación con la traducción.
tr
Es probable que dos llamadas sean más rápidas que una sola llamada a herramientas más complejas, pero esto depende mucho del tamaño de entrada, de las proporciones de los diferentes caracteres, de la implementacióntr
y de las herramientas de la competencia, del sistema operativo, del número de núcleos, etc.fuente
tr -s '[:upper:] [:punct:]' '[:lower:]\n' <doyle_sherlock_holmes.txt
printf 'A.AAAA,A' | tr -s '[:upper:] [:punct:]' '[:lower:][\n*]'
getsa\na\na'
, y la transformación para... '[:lower:]\n'
podría no necesariamente hacer nada de todos'[:punct:]'
modos: algunostr
s truncarán set1 para que coincida con 2 y algunos harán un implícito[\n*]
. Es mejor usar el rango allí.Aquí hay algunos enfoques:
GNU
grep
ytr
: encuentra todas las palabras y en minúsculasGNU grep y perl: como arriba pero perl maneja la conversión a minúsculas
perl: encuentre todos los caracteres alfabéticos e imprímalos en minúsculas (gracias @steeldriver):
sed: elimine todos los caracteres que no sean alfabéticos o espacios, sustituya todos los caracteres alfabéticos con sus versiones en minúsculas y reemplace todos los espacios con líneas nuevas. Tenga en cuenta que esto supone que todos los espacios en blanco son espacios, no pestañas.
fuente
perl -lne 'print lc for /[[:alpha:]]+/g'
también funcionaría? o es de mal estilo? (¡Soy nuevo en Perl e intento aprender!)sed -z 's/\W*\(\w\+\)\W*/\L\1\n/g'
sed
puedes hacer\w
ahora? ¡Frio!sed
's-z
ero delimitan interruptor - que los ciclos más de\0NUL
s en lugar de saltos de línea. Bastante genial cuando haces algo comotar -c . | tr -s \\0 | sed -z ...
, pero un poco lento.Si. Puede hacer eso con
tr
una configuración regional ASCII (que es, para un GNU detr
todos modos, algo así como su único alcance) . Puede usar las clases POSIX, o puede hacer referencia a los valores de bytes de cada carácter por número octal. También puede dividir sus transformaciones en rangos.El comando anterior transformaría todos los caracteres en mayúsculas a minúsculas, ignoraría por completo los caracteres en minúsculas y transformaría todos los demás caracteres a nuevas líneas. Por supuesto, entonces terminas con un montón de líneas en blanco. Las
tr
-s
repeticiones queeze detector puede resultar útil en ese caso, pero si lo usa junto con el[:upper:]
de[:lower:]
la transformación, entonces terminan apretando los caracteres en mayúsculas también. De esa manera, todavía requiere un segundo filtro como ......o...
... y entonces resulta ser mucho menos conveniente que hacerlo ...
... que exprime la
-c
secuencia de caracteres alfabéticos por secuencia en una sola línea nueva de una pieza, luego hace la transformación de arriba a abajo en el otro lado de la tubería.Eso no quiere decir que los rangos de esa naturaleza no sean útiles. Cosas como:
... puede ser bastante útil ya que convierte los bytes de entrada a todos los dígitos en un amplio espectro de sus valores. No desperdicies, no quieras, ya sabes.
Otra forma de hacer la transformación podría involucrar
dd
.Debido a que
dd
puede hacer ambas cosasunblock
ylcase
conversiones al mismo tiempo, incluso podría ser posible pasarle gran parte del trabajo. Pero eso solo puede ser realmente útil si puede predecir con precisión el número de bytes por palabra, o al menos puede rellenar cada palabra con espacios de antemano a un recuento de bytes predecible, porqueunblock
come espacios finales al final de cada bloque.fuente
dd
participar :)