Bash convert string para array de strings?

1

Eu tenho uma string como esta:

8080 "ac ac df asd" 9019 "f v adfs" 1 "123 da 123x"

Existe uma maneira inteligente de converter isso em matrizes como essa usando o Bash?

8080 "ac ac df asd"
9019 "f v adfs"
1 "123 da 123x"
    
por shomel 10.07.2015 / 13:56

3 respostas

1
# define function
foo() { while [ -n "$2" ]; do array+=( "\"$1\" \"$2\"" ); shift 2; done; }

# call function with string
foo 8080 "ac ac df asd" 9019 "f v adfs" 1 "123 da 123x"

# print array
printf "%s\n" "${array[@]}"

Saída:

"8080" "ac ac df asd"
"9019" "f v adfs"
"1" "123 da 123x"
    
por 10.07.2015 / 18:30
1

Acho que isso é o que você quer, supondo que não há problema em usar sed .

Exemplo

$ echo '8080 "ac ac df asd" 9019 "f v adfs" 1 "123 da 123x"' | sed 's/" \([0-9]\)/"\n/g'
8080 "ac ac df asd"
9019 "f v adfs"
1 "123 da 123x"

A abordagem que você está procurando é reconhecer um padrão e substituí-lo por um caractere de nova linha, \n . O padrão que estamos reconhecendo com sed é uma citação seguida por um espaço, seguido por um dígito.

" ...digit...

Nessas situações, queremos colocar um \n após o espaço " +. Dado que o espaço agora ocorrerá no final da linha, podemos soltá-lo, daí, "\n . OBSERVAÇÃO: O é uma variável na qual salvamos o dígito quando fizemos isso no lado correspondente em s/..match../..replace../g in sed , ou seja, \([0-9]\) . Você pode salvar partes de strings em sed quando você as envolve com parens com escape, \(..save this..\) .

    
por 10.07.2015 / 15:06
1

Isso dividirá seus valores em itens de matriz separados, que você poderá unir. Tenho certeza de que há uma maneira melhor, mas isso fornece a saída que você solicitou da entrada que você forneceu. Se esta for a entrada do usuário (ou se for entrada fora do seu controle) a seguinte solução não deve ser usada no caso de backticks ou substituições de variáveis são oferecidas ao eval .

s='8080 "ac ac df asd" 9019 "f v adfs" 1 "123 da 123x"'
eval t=("$s")                                   # Incautious array assignment

a=()
for k in $(seq 0 $(( (${#t[@]}+1) /2 -1 )) )    # Count pairs of elements
do
    p1=$((k*2)) p2=$((k*2 +1))                  # Indexes into original list
    a+=("${t[$p1]} \"${t[$p2]}\"")              # New element is a pair of originals
done

for p in "${a[@]}"                              # Report elements of array a[]
do
    echo "item> $p" >&2
done

Este código pressupõe que o segundo de cada par requer cotações (elas são removidas durante o eval ). Você poderia talvez tornar isso mais inteligente adicionando aspas em torno de um valor apenas se esse valor contivesse espaços em branco, mas eu não fiz isso aqui.

    
por 10.07.2015 / 15:36