Sé que el cut
comando puede imprimir los primeros n
caracteres de una cadena, pero ¿cómo seleccionar los últimos n
caracteres?
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.-P
evita 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 -c
simplemente funciona. Por lo tanto, se puede utilizar si el conjunto de caracteres esASCII
,ISO 8859-1
o una variante.Si tiene una entrada Unicode, como en el
UTF-8
formato 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
-m
puede contar al menos los caracteres Unicode reales:Ok, los últimos 6 bytes nos darán los últimos 3 caracteres:
Por lo tanto,
tail
no 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:
tail
es 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
,tail
ycut
, no está internacionalizado todavía completamente. Que se trata principalmente de soportar Unicode.Por ejemplo,
cut
serí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
/--chars
es, 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
cut
solución basada en Glenn Jackman no parecen hacerlo.tail
debe 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/syslog
tail -c3 -n10 /var/log/syslog
le 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
,zsh
omksh
shell: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
zsh
oyash
es:fuente
${STRING:(-3):3}
(especificando el campo de longitud ),${STRING: -3}
(con un espacio entre el:
y el-
), o${STRING: -3:3}
.3
es 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
$var
gusta:... y luego se despoja de la cabeza de
$var
todo, 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
$var
no contiene al menos tres caracteres nada pero el de salida\n
se imprime ewline. Por otra parte, si desea que se imprima en ese caso, necesita un paso adicional como:De esa manera
$last3
solo está vacío si$var
contiene 3 o menos bytes. Y$var
solo se sustituye$last3
si$last3
está vacío ounset
, y sabemos que no esunset
porque lo configuramos.fuente
printf
cadenas de formato?${VARNAME:(-3)}
(presumiendobash
)?bash
como en cualquier otro shell que reclame la compatibilidad POSIX.csh
es 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.ksh
csh
ksh
csh
csh
Puedes 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
,rev
Requerirá algo como esto:LC_ALL=en_US.UTF-8
Solució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
echo
Cuál es tu fuente a prueba de balas?decode/encode
es mi fuente a prueba de balas. Limpié mi respuesta.LC_ALL=C
porque 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.A
Se espera que los elementos @ARGV sean cadenas codificadas en UTF-8,O
STDOUT 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 | rev
fuente
rev
solució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
printf
no funciona, entonces estás haciendo algo muy mal.printf $str
(en lugar deprintf "$str"
oprintf '%s' "$str"
). Y sí,printf $str
está muy mal. (echo -n $str
no es mucho mejor.)