Respuestas:
Puede usar operadores de cadena :
$ foo=1:2:3:4:5
$ echo ${foo##*:}
5
Esto recorta todo desde el frente hasta un ':', con avidez.
${foo <-- from variable foo
## <-- greedy front trim
* <-- matches anything
: <-- until the last ':'
}
${foo%:*}
. #
- desde el principio; %
- desde el final. #
, %
- partido más corto; ##
, %%
- partido más largo.
echo ${pwd##*/}
No funciona.
pwd
como una variable. Tratar dir=$(pwd); echo ${dir##*/}
. ¡Funciona para mi!
Otra forma es revertir antes y después cut
:
$ echo ab:cd:ef | rev | cut -d: -f1 | rev
ef
Esto hace que sea muy fácil obtener el último pero un campo, o cualquier rango de campos numerados desde el final.
echo "1 2 3 4" | rev | cut -d " " -f1 | rev
rev
era justo lo que necesitaba! cut -b20- | rev | cut -b10- | rev
Es difícil obtener el último campo usando cortar, pero aquí hay algunas soluciones en awk y perl
echo 1:2:3:4:5 | awk -F: '{print $NF}'
echo 1:2:3:4:5 | perl -F: -wane 'print $F[-1]'
/
carácter final : /a/b/c/d
y /a/b/c/d/
producen el mismo resultado ( d
) al procesar pwd | awk -F/ '{print $NF}'
. La respuesta aceptada da como resultado un resultado vacío en el caso de/a/b/c/d/
/
como delimitador, y si su ruta es /my/path/dir/
, usará el valor después del último delimitador, que es simplemente una cadena vacía. Por lo tanto, es mejor evitar la barra diagonal final si necesita hacer algo como yo.
awk '{$NF=""; print $0}' FS=: OFS=:
menudo funciona lo suficientemente bien.
Suponiendo un uso bastante simple (sin escapar del delimitador, por ejemplo), puede usar grep:
$ echo "1:2:3:4:5" | grep -oE "[^:]+$"
5
Desglose: encuentre todos los caracteres, no el delimitador ([^:]) al final de la línea ($). -o solo imprime la parte correspondiente.
De una sola mano:
var1="1:2:3:4:5"
var2=${var1##*:}
Otro, usando una matriz:
var1="1:2:3:4:5"
saveIFS=$IFS
IFS=":"
var2=($var1)
IFS=$saveIFS
var2=${var2[@]: -1}
Otro más con una matriz:
var1="1:2:3:4:5"
saveIFS=$IFS
IFS=":"
var2=($var1)
IFS=$saveIFS
count=${#var2[@]}
var2=${var2[$count-1]}
Usando expresiones regulares Bash (versión> = 3.2):
var1="1:2:3:4:5"
[[ $var1 =~ :([^:]*)$ ]]
var2=${BASH_REMATCH[1]}
$ echo "a b c d e" | tr ' ' '\n' | tail -1
e
Simplemente traduzca el delimitador a una nueva línea y elija la última entrada con tail -1
.
\n
, pero para la mayoría de los casos es la solución más fácil de leer.
Utilizando sed
:
$ echo '1:2:3:4:5' | sed 's/.*://' # => 5
$ echo '' | sed 's/.*://' # => (empty)
$ echo ':' | sed 's/.*://' # => (empty)
$ echo ':b' | sed 's/.*://' # => b
$ echo '::c' | sed 's/.*://' # => c
$ echo 'a' | sed 's/.*://' # => a
$ echo 'a:' | sed 's/.*://' # => (empty)
$ echo 'a:b' | sed 's/.*://' # => b
$ echo 'a::c' | sed 's/.*://' # => c
Si su último campo es un solo carácter, puede hacer esto:
a="1:2:3:4:5"
echo ${a: -1}
echo ${a:(-1)}
Verifique la manipulación de cadenas en bash .
a
, no el último campo .
Aquí hay muchas buenas respuestas, pero aún quiero compartir esta usando basename :
basename $(echo "a:b:c:d:e" | tr ':' '/')
Sin embargo , fallará si ya hay algunos '/' en su cadena . Si slash / es su delimitador, entonces solo tiene que (y debería) usar basename.
No es la mejor respuesta, pero solo muestra cómo puedes ser creativo usando los comandos bash.
Usando Bash.
$ var1="1:2:3:4:0"
$ IFS=":"
$ set -- $var1
$ eval echo \$${#}
0
echo ${!#}
lugar de eval echo \$${#}
.
for x in `echo $str | tr ";" "\n"`; do echo $x; done
Para aquellos que se sienten cómodos con Python, https://github.com/Russell91/pythonpy es una buena opción para resolver este problema.
$ echo "a:b:c:d:e" | py -x 'x.split(":")[-1]'
De la ayuda pythonpy: -x treat each row of stdin as x
.
Con esa herramienta, es fácil escribir código python que se aplica a la entrada.
Puede ser un poco tarde con la respuesta, aunque una solución simple es invertir el orden de la cadena de entrada. Esto le permitiría obtener siempre el último elemento sin importar la longitud.
[chris@desktop bin]$ echo 1:2:3:4:5 | rev | cut -d: -f1
5
Sin embargo, es importante tener en cuenta que si usa este método y los números tienen más de 1 dígito (o más de un carácter en cualquier circunstancia), deberá ejecutar otro comando 'rev' sobre la salida canalizada.
[chris@desktop bin]$ echo 1:2:3:4:5:8:24 | rev | cut -d: -f1
42
[chris@desktop bin]$ echo 1:2:3:4:5:8:24 | rev | cut -d: -f1 | rev
24
Espero poder ayudar, salud
Si le gusta python y tiene una opción para instalar un paquete, puede usar esta utilidad python .
# install pythonp
pythonp -m pip install pythonp
echo "1:2:3:4:5" | pythonp "l.split(':')[-1]"
5
echo "1:2:3:4:5" | python -c "import sys; print(list(sys.stdin)[0].split(':')[-1])"
pythonp
paquete es hacer que hagas lo mismo que python -c
con menos tipos de caracteres. Eche un vistazo al archivo README en el repositorio.
La coincidencia de expresiones regulares en sed
es codiciosa (siempre va a la última aparición), que puede utilizar para su ventaja aquí:
$ foo=1:2:3:4:5
$ echo ${foo} | sed "s/.*://"
5
5
si la cadena lo es1:2:3:4:5:
(al usar los operadores de cadena se obtiene un resultado vacío). Esto es especialmente útil al analizar rutas que podrían contener (o no) un/
carácter final .