Como converter um String em Array no shell script

2

Eu já li Como dividir um string em uma matriz no bash mas a questão parece um pouco diferente para mim, então eu vou perguntar usando meus dados.

Eu tenho essa linha vindo da STDIN:

(5,[a,b,c,d,e,f,g,h,i,j])

O cinco é meu ID de grupo e as letras são valores de uma matriz (os dados do grupo). Eu preciso colocar o ID do grupo em um var e as letras em algo que eu possa trabalhar usando IFS=',' read -r -a array <<< "$tline"

    
por Magno C 03.10.2017 / 03:37

4 respostas

5
bkpIFS="$IFS"

IFS=',()][' read -r -a array <<<"(5,[a,b,c,d,e,f,g,h,i,j])"
echo ${array[@]}    ##Or printf "%s\n" ${array[@]}
5 a b c d e f g h i j

IFS="$bkpIFS"

Explicações:

Ou usando awk e sua função split .

awk '{split($0,arr,/[][,)(]/)} 
    END{for (x in arr) printf ("%s ",arr[x]);printf "\n"}' <<<"(5,[a,b,c,d,e,f,g,h,i,j])"

Explicações:

  • O mesmo aqui, estamos dividindo toda a linha de entrada com base no grupo definido de delimitadores [...] na constante de regexp /[...]/ , que suporta na implementação moderna da função awk using split . leia mais na seção de split() function.

  • Em seguida, na coluna END{for (x in arr) printf ("%s ",arr[x]); ...} , estamos passando por um array chamado arr e imprimimos o valor correspondente. x aqui aponta para o índice da matriz arr elements. leia mais sobre as regras de BEGIN / END do awk .

Redirecionamento lateral para Como adicionar / remover um elemento na matriz no bash? .

    
por 03.10.2017 / 08:04
3
data=$(tr -d '[]()' | tr ',' '\n')

readarray -t -n 1 group   <<<"$data"
readarray -t -s 1 letters <<<"$data"

printf 'group = %s\n' "$group"
printf 'data: %s\n' "${letters[@]}"

Isso primeiro eliminará todos os () e [] dos dados de entrada que chegam na entrada padrão usando tr e, em seguida, substituirá as vírgulas por novas linhas e atribuirá o resultado a data .

Em seguida, usamos readarray para analisar esses dados.

A primeira chamada apenas lerá a primeira entrada (com -n 1 ) e a atribuirá à variável group .

A segunda chamada para readarray ignorará a primeira entrada (com -s 1 ) e atribuirá as entradas restantes à matriz letters .

O -t remove as novas linhas reais de cada entrada.

Mesmo que group seja uma matriz aqui, ela contém apenas um único elemento e você pode usá-lo como $group .

$ echo '(5,[a,b,c,d,e,f,g,h,i,j])' | bash ./script.sh
group = 5
data: a
data: b
data: c
data: d
data: e
data: f
data: g
data: h
data: i
data: j

O seguinte retém as vírgulas na string e permite que readline as use para delimitar as entradas, mas, por algum motivo, o último elemento de letters tem uma nova linha no final:

data=$(tr -d '[]()')
readarray -d, -t -s 1 letters <<<"$data"

printf '>%s<\n' "${letters[@]}"

Em exibição:

$ echo '(5,[a,b,c,d,e,f,g,h,i,j])' | bash ./script.sh
>a<
>b<
>c<
>d<
>e<
>f<
>g<
>h<
>i<
>j
<
    
por 03.10.2017 / 08:48
2

POSIXly:

string='(5,[a,b,c,d,e,f,g,h,i,j])'
set -o noglob
IFS=',['
string=${string#'('}
string=${string%'])'}
set -- $string''
gid=$1; shift 2
printf '%s\n' "gid=$gid; group-data:"
printf '   <%s>\n' "$@"

Ele deve funcionar com qualquer valor para os campos de dados do grupo, mesmo aqueles com caracteres de nova linha.

    
por 03.10.2017 / 16:37
0

Devido à formatação de seus dados, read não os colocaria em um array de forma limpa. sed pode ser usado para "limpar" os dados.

declare -a TLINEARRAY
TLINEARRAY=($(sed -e 's/,/ /g' -e 's/\[/ /g' -e 's/\]//g' <<< "$tline" ))
echo ${TLINEARRAY[*]}

Usando read como você tentou.

read -a TLINEARRAY <<< "$(sed -e 's/,/ /g' -e 's/\[/ /g' -e 's/\]//g' <<< "$tline" )"
echo ${TLINEARRAY[*]}

Ambos os métodos geram uma matriz contendo 5 a b c d e f g h i j .

    
por 03.10.2017 / 07:38