Tengo una cadena:
one_two_three_four_five
Necesito guardar en un A
valor variable two
y en un B
valor variable four
de la cadena anterior
Use cut
con _
como delimitador de campo y obtenga los campos deseados:
A="$(cut -d'_' -f2 <<<'one_two_three_four_five')"
B="$(cut -d'_' -f4 <<<'one_two_three_four_five')"
También puedes usar echo
y pipe en lugar de Here string:
A="$(echo 'one_two_three_four_five' | cut -d'_' -f2)"
B="$(echo 'one_two_three_four_five' | cut -d'_' -f4)"
Ejemplo:
$ s='one_two_three_four_five'
$ A="$(cut -d'_' -f2 <<<"$s")"
$ echo "$A"
two
$ B="$(cut -d'_' -f4 <<<"$s")"
$ echo "$B"
four
$ echo $FILE
my_user/my_folder/file.csv
$ A="$(cut -d'/' -f2 <<<"$FILE")"
$ echo $A
[file]*
¿Sabes lo que está pasando aquí?echo "${s##*_}"
Usando solo construcciones sh POSIX, puede usar construcciones de sustitución de parámetros para analizar un delimitador a la vez. Tenga en cuenta que este código supone que existe el número requerido de campos; de lo contrario, se repite el último campo.
Alternativamente, puede usar una sustitución de parámetro sin comillas con la expansión de comodín deshabilitada y
IFS
configurada en el carácter delimitador (esto solo funciona si el delimitador es un solo carácter que no es un espacio en blanco o si alguna secuencia de espacios en blanco es un delimitador).Esto cambia los parámetros posicionales. Si hace esto en una función, solo se ven afectados los parámetros posicionales de la función.
Otro enfoque es usar el
read
incorporado.fuente
unset IFS
no vuelveIFS
al valor predeterminado. Si después de eso alguienOldIFS="$IFS"
tiene un valor nulo dentro de OldIFS. Además, se supone que el valor anterior de IFS es el predeterminado, que es muy posible (y útil) no ser. La única solución correcta es almacenarold="$IFS"
y luego restaurar con IFS = "$ old". O ... usa un sub-shell(...)
. O, mejor aún, lea mi respuesta.unset IFS
no restauraIFS
el valor predeterminado, pero devuelve la división de campo al efecto predeterminado. Sí, es una limitación, pero generalmente es aceptable en la práctica. El problema con una subshell es que necesitamos extraer datos de ella. Muestro una solución que no cambia el estado al final, conread
. (Funciona en shells POSIX, pero IIRC no en el shell Bourne porque se ejecutaríaread
en un subshell debido al documento here.) El uso<<<
como en su respuesta es una variante que funciona solo en ksh / bash / zsh.user/my_folder/[this_is_my_file]*
? Lo que obtengo cuando sigo estos pasos es[this_is_my_file]*
/
.Quería ver una
awk
respuesta, así que aquí hay una:fuente
awk -F_ '{print $NF}' <<< 'one_two_3_4_five'
La forma más simple (para conchas con <<<) es:
Usando una variable temporal en
$a
lugar de$_
porque un shell se queja.En un guión completo:
No cambia IFS, no hay problemas con
set -f
(expansión de nombre de ruta) No hay cambios en los parámetros posicionales ("$ @")Para una solución portátil a todos los shells (sí, todos los POSIX incluidos) sin cambiar IFS o
set -f
, use el equivalente de heredoc (un poco más complejo):Comprenda que estas soluciones (tanto el documento here-doc como el uso de
<<<
eliminarán todas las nuevas líneas finales.Y que esto está diseñado para un contenido variable de "una línea". Las
soluciones para líneas múltiples son posibles pero necesitan construcciones más complejas.
Una solución muy simple es posible en bash versión 4.4
No hay un equivalente para los shells POSIX, ya que muchos shells POSIX no tienen arrays.
Para los shells que tienen arrays pueden ser tan simples como:
(probado trabajando en attsh, lksh, mksh, ksh y bash)
Pero con muchas tuberías adicionales para mantener y restablecer variables y opciones:
En zsh, las matrices comienzan en 1 y no divide la cadena de forma predeterminada.
Por lo tanto, se deben hacer algunos cambios para que esto funcione en zsh.
fuente
read
son simples siempre que OP no quiera extraer los elementos 76 y 127 de una cadena larga ...readarray
podría ser más fácil de usar para esa situación.Con
zsh
usted podría dividir la cadena (en_
) en una matriz:y luego acceda a cada elemento mediante el índice de matriz:
Tenga en cuenta que los índices de matriz
zsh
(a diferencia deksh
/bash
) comienzan en 1 .fuente
set -f
advertencia a la primera solución. ... asteriscos*
tal vez?set -f
? No estoy usandoread
/IFS
. Pruebe mis soluciones con una cadena como*_*_*
o lo que sea ...¿Se permite una solución de Python?
fuente
Otro ejemplo awk; Más simple de entender.
Se puede usar con variables también.
Supongamos:
this_str = "one_two_three_four_five"
Entonces lo siguiente funciona:
A = `echo $ {this_str} | awk -F_ '{print $ 1}' `
B =` echo $ {this_str} | awk -F_ '{print $ 2}' '
C = `echo $ {this_str} | awk -F_ '{print $ 3}' '
... y así sucesivamente ...
fuente