Sé que el cutcomando puede imprimir los primeros ncaracteres de una cadena, pero ¿cómo seleccionar los últimos ncaracteres?
Si tengo una cadena con un número variable de caracteres, ¿cómo puedo imprimir solo los últimos tres caracteres de la cadena? p.ej.
la salida "ilimitada" necesaria es "ted" La salida "987654" necesaria es "654" La salida "123456789" necesaria es "789"
text-processing
cut
Odisea
fuente
fuente

grep -o '.\{3\}$'echo "unlimited" | python -c "print raw_input()[-3:]""echo unlimited" | java -jar EnterpriseWordTrimmer.jar, pero no creo que sea realmente necesario introducir un lenguaje más pesado para la manipulación de personajes.java -server -Xms300M -Xmx3G -XX:+UseParallelGC -cp /path/to/all/the/jars/ -Dinput.interactive=false -Dinput.pipe=true -Dconfig.file=/path/to/config/last-three-letters.cfg -jar ...grep -o -P '.{0,3}$'imprimirá los últimos 3 caracteres incluso si la línea tiene menos de 3 caracteres.-Pevita tener que escapar de los aparatos ortopédicos.Manteniéndolo simple - cola
No deberíamos necesitar una expresión regular, o más de un proceso, solo para contar caracteres.
El comando
tail, que a menudo se usa para mostrar las últimas líneas de un archivo, tiene una opción-c(--bytes), que parece ser la herramienta adecuada para esto:(Cuando está en un shell, tiene sentido usar un método como en la respuesta de mikeserv, porque ahorra iniciar el proceso para
tail).Personajes reales de Unicode?
Ahora, pides los últimos tres caracteres ; Eso no es lo que te da esta respuesta: ¡genera los últimos tres bytes !
Siempre que cada carácter sea un byte,
tail -csimplemente funciona. Por lo tanto, se puede utilizar si el conjunto de caracteres esASCII,ISO 8859-1o una variante.Si tiene una entrada Unicode, como en el
UTF-8formato común , el resultado es incorrecto:En este ejemplo, usando
UTF-8, los caracteres griegos alfa, beta y gamma tienen dos bytes de longitud:La opción
-mpuede contar al menos los caracteres Unicode reales:Ok, los últimos 6 bytes nos darán los últimos 3 caracteres:
Por lo tanto,
tailno admite el manejo de caracteres generales, y ni siquiera lo intenta (ver más abajo): maneja líneas de tamaño variable, pero no caracteres de tamaño variable.Digámoslo de esta manera:
tailes correcto para la estructura del problema a resolver, pero incorrecto para el tipo de datos.GNU coreutils
Mirando más, resulta que los que te coreutils GNU, el conjunto de herramientas básicas como
sed,ls,tailycut, no está internacionalizado todavía completamente. Que se trata principalmente de soportar Unicode.Por ejemplo,
cutsería un buen candidato para usar en lugar de la cola aquí para el soporte del personaje; Tiene opciones para trabajar en bytes o caracteres,-c(--bytes) y-m(--chars);¡Solo eso
-m/--charses, a partir de la versióncut (GNU coreutils) 8.21, 2013,no implementado!
De
info cut:Consulte también esta respuesta a ¿No puede usar `cut -c` (` --characters`) con UTF-8? .
fuente
cutsolución basada en Glenn Jackman no parecen hacerlo.taildebe tratar con bytes y no con caracteres. Una vez hice un parche para agregar una nueva opción para seleccionar también personajes, pero creo que nunca se fusionaron: - /tail -c3 -n10 /var/log/syslogtail -c3 -n10 /var/log/syslogle pide las últimas 10 líneas, y eso funciona para mí. Utiliza la opción-c3, y luego la opción conflictiva-n10. La última opción tiene prioridad.Si el texto está en una variable de entorno llamada
STRING, usted puede hacer esto en unabash,zshomkshshell:O
que también tiene el beneficio de trabajar con ksh93 de donde proviene esa sintaxis.
El punto es que el
:tiene que ser separado del-, de lo contrario se convierte en el${var:-default}operador del shell Bourne.La sintaxis equivalente en los shells
zshoyashes:fuente
${STRING:(-3):3}(especificando el campo de longitud ),${STRING: -3}(con un espacio entre el:y el-), o${STRING: -3:3}.3es algo discutible, ya que es pedir "los tres caracteres del tercero desde el último carácter, inclusive", que resulta ser una operación idéntica en términos prácticos a "Todos los caracteres en adelante desde el tercero desde el último , inclusive ".Utilizando
awk:fuente
Si la cadena está en una variable, puede hacer:
Eso despoja a los últimos tres caracteres del valor de me
$vargusta:... y luego se despoja de la cabeza de
$vartodo, excepto de lo que se acaba de quitar:Este método tiene sus ventajas y desventajas. En el lado positivo, es totalmente portátil POSIX y debería funcionar en cualquier carcasa moderna. Además, si
$varno contiene al menos tres caracteres nada pero el de salida\nse imprime ewline. Por otra parte, si desea que se imprima en ese caso, necesita un paso adicional como:De esa manera
$last3solo está vacío si$varcontiene 3 o menos bytes. Y$varsolo se sustituye$last3si$last3está vacío ounset, y sabemos que no esunsetporque lo configuramos.fuente
printfcadenas de formato?${VARNAME:(-3)}(presumiendobash)?bashcomo en cualquier otro shell que reclame la compatibilidad POSIX.cshes uno de los proyectiles modernos compatibles con POSIX que menciono aquí, desafortunadamente. La especificación POSIX-shell se modela después , que se modela a sí misma después de una combinación de ambos y los shells tradicionales de estilo Bourne. incorporó la excelente funcionalidad de control de trabajo y la antigua redirección de E / S de los estilos Bourne. También agregó algunas cosas, como los conceptos de manipulación de cadenas que demuestro arriba. Es probable que esto no funcione en ningún tradicional , que yo sepa, lamento decirlo.kshcshkshcshcshPuedes hacer esto, pero esto es un poco ... excesivo:
fuente
La solución a prueba de balas para cadenas utf-8:
O usar:
para evitar el manejo de datos con formato incorrecto.
Ejemplo:
Produce algo como esto:
No depende de la configuración regional (es decir, funciona con
LC_ALL=C).Bash,sed,grep,awk,revRequerirá algo como esto:LC_ALL=en_US.UTF-8Solución común:
Puede detectar la codificación con uchardet . Ver también proyectos relacionados .
Puede decodificar / codificar con Encode en Perl, códecs en Python 2.7
Ejemplo :
Extraiga los últimos tres caracteres de la cadena utf-16le y convierta estos caracteres a utf-8
Ver también: perlunitut , Python 2 Unicode HOWTO
fuente
echoCuál es tu fuente a prueba de balas?decode/encodees mi fuente a prueba de balas. Limpié mi respuesta.LC_ALL=Cporque es una configuración muy "tonta", pero puede romperse cuando intenta pasar una cadena UTF-8 a SHIFT-5, o una cadena SHIFT-5 a KOI8, etc.perl -CAO -e 'print substr($ARGV[0], -3)'funciona bien.ASe espera que los elementos @ARGV sean cadenas codificadas en UTF-8,OSTDOUT estará en UTF-8.utf8_str¿Qué pasa con el uso de "expr" o "rev"?
Una respuesta similar a la proporcionada por @ G-Man :
expr "$yourstring" : '.*\(...\)$'tiene el mismo inconveniente que la solución grep.Un truco bien conocido es combinar "cortar" con "rev":
echo "$yourstring" | rev | cut -n 1-3 | revfuente
revsolución se parece mucho a Glenn JackmanObtenga el tamaño de la cadena con:
Luego obtenga la subcadena del último n carácter:
Por ejemplo:
daría:
fuente
tail -n 1 revisiones.log | awk '{print substr ($ 0, 0, length ($ 0) - (length ($ 0) -13))}'
Si desea imprimir los primeros trece caracteres del principio
fuente
printf no funcionará si la cadena tiene espacios en ella.
Debajo del código para la cadena con espacio
fuente
printfno funciona, entonces estás haciendo algo muy mal.printf $str(en lugar deprintf "$str"oprintf '%s' "$str"). Y sí,printf $strestá muy mal. (echo -n $strno es mucho mejor.)