separar into how array arrays string bash delimited-text

arrays - into - Convertir una matriz Bash en una cadena delimitada



split line by delimiter bash (3)

Me gustaría saber lo siguiente;

  1. Por qué el ejemplo que no funciona no funciona.
  2. Si hay otros métodos más limpios que los dados en el ejemplo de trabajo.

Ejemplo no funcional

> ids=(1 2 3 4);echo ${ids[*]// /|} 1 2 3 4 > ids=(1 2 3 4);echo ${${ids[*]}// /|} -bash: ${${ids[*]}// /|}: bad substitution > ids=(1 2 3 4);echo ${"${ids[*]}"// /|} -bash: ${"${ids[*]}"// /|}: bad substitution

Ejemplo de trabajo

> ids=(1 2 3 4);id="${ids[@]}";echo ${id// /|} 1|2|3|4 > ids=(1 2 3 4); lst=$( IFS=''|''; echo "${ids[*]}" ); echo $lst 1|2|3|4

En contexto, la cadena delimitada que se utilizará en un comando sed para un análisis posterior.


También puede usar printf , sin comandos externos o la necesidad de manipular IFS:

ids=(1 2 3 4) # create array printf -v ids_d ''|%s'' "${ids[@]}" # yields "|1|2|3|4" ids_d=${ids_d:1} # remove the leading ''|''


Tu primera pregunta ya está abordada en la respuesta de F. Hauri. Aquí hay una forma canónica de unir los elementos de una matriz:

ids=( 1 2 3 4 ) IFS=/| eval ''lst="${ids[*]}"''

Algunas personas gritarán en voz alta que eval es malvado, sin embargo, es perfectamente seguro aquí, gracias a las comillas simples. Esto solo tiene ventajas: no hay subshells, IFS no se modifica globalmente, no recortará las nuevas líneas finales y es muy simple.


# REVISION: 2017-03-14 # Use of read and other bash specific features (bashisms)

Como los paréntesis se utilizan para delimitar una matriz , no una cadena:

ids="1 2 3 4";echo ${ids// /|} 1|2|3|4

Algunas muestras: Poblando $ids con dos cadenas: ab y cd

ids=("a b" "c d") echo ${ids[*]// /|} a|b c|d IFS=''|'';echo "${ids[*]}";IFS=$'' /t/n'' a b|c d

... y finalmente:

IFS=''|'';echo "${ids[*]// /|}";IFS=$'' /t/n'' a|b|c|d

Donde se ensambla la matriz, separados por 1er carácter de $IFS , pero con espacio reemplazado por | en cada elemento de la matriz.

Cuando tu lo hagas:

id="${ids[@]}"

transfiere la construcción de cadena de la fusión de los ids matriz por un espacio a una nueva variable de tipo cadena .

Nota: cuando "${ids[@]}" proporcione una cadena separada por espacios , "${ids[*]}" (con una estrella * lugar del signo @ ) representará una cadena separada por el primer carácter de $IFS .

lo que el man bash dice:

man -Len -Pcol/ -b bash | sed -ne ''/^ *IFS /{N;N;p;q}'' IFS The Internal Field Separator that is used for word splitting after expansion and to split lines into words with the read builtin command. The default value is ``<space><tab><newline>''''.

Jugando con $IFS :

set | grep ^IFS= IFS=$'' /t/n''

declare -p IFS declare -- IFS=" " printf "%q/n" "$IFS" $'' /t/n''

Literalmente un space , una tabulation y (significado o) un line-feed . Entonces, mientras que el primer personaje es un espacio. el uso de * hará lo mismo que @ .

Pero

{

# OIFS="$IFS" # IFS=$'': /t/n'' # unset array # declare -a array=($(echo root:x:0:0:root:/root:/bin/bash))

IFS=: read -a array < <(echo root:x:0:0:root:/root:/bin/bash) echo 1 "${array[@]}" echo 2 "${array[*]}" OIFS="$IFS" IFS=: echo 3 "${array[@]}" echo 4 "${array[*]}" IFS="$OIFS" } 1 root x 0 0 root /root /bin/bash 2 root x 0 0 root /root /bin/bash 3 root x 0 0 root /root /bin/bash 4 root:x:0:0:root:/root:/bin/bash

Nota: La línea IFS=: read -a array < <(...) usará : como separador, sin establecer $IFS permanentemente. Esto se debe a que la línea de salida #2 presenta espacios como separadores.