2016-06-14 16 views
6

In Bash, voglio annullare l'impostazione di una voce di hashmap. Ma ho fallito. Il codice è come di seguito:Bash hashmap utilizzando il preventivo come chiave

declare -A arr 
arr["a'b"]=3 
echo ${!arr[@]} ## output: a'b 
key="a'b" 
unset arr[$key] ## error: -bash: unset: `arr[a'b]': not a valid identifier 

Come posso disinserire questa voce?

+0

['unset arr [" $ key "]'] (http://mywiki.wooledge.org/BashGuide/Practices#Quoting)? ** EDIT **: Questo non funziona ... – anishsane

+1

Sembra un bug in bash – Leon

+0

Hmm ... mio male ... Inoltre, 'arr ['$ x'] = 123; unset arr ['$ x'] 'fornisce' -bash: unset: [$ x]: indice di array non valido ' – anishsane

risposta

5

Basta usare le virgolette singole:

$ declare -A arr=(["a'b"]=3 [foo]=bar) 
$ declare -p arr 
declare -A arr='(["a'\''b"]="3" [foo]="bar")' 
$ key="a'b" 
$ unset 'arr[$key]' 
$ declare -p arr 
declare -A arr='([foo]="bar")' 

FATTO!

+0

modo brillante! – ruanhao

+1

Questo è magico. È documentato che 'unset' fa un secondo round di espansione? –

+0

@glennjackman: non l'ho visto documentato, davvero, ma non è specifico per 'unset'. Il contesto aritmetico mostra anche questo comportamento: 'declare -A glenn; key = '$ (ls> &2)'; ((glenn [$ key])). "Sorpresa, la risposta è probabilmente nella fonte':) '. Bash ha un modo davvero pazzesco di analizzare le cose. –

4

Ingannevole. Puoi farlo manualmente sfuggendo alla citazione singola "interiore":

$ declare -A arr=(["a'b"]=3 [foo]=bar) 
$ key="a'b" 
$ unset "arr[$key]" 
bash: unset: `arr[a'b]': not a valid identifier 
$ unset "arr[a\'b]" 
$ declare -p arr 
declare -A arr='([foo]="bar")' 

Ma come farlo "programmaticamente"? Fortunatamente bash ha un meccanismo per "fuga" di una stringa: printf "%q":

$ declare -A arr=(["a'b"]=3 [foo]=bar) 
$ echo "$key" 
a'b 
$ printf "%q" "$key" 
a\'b 
$ unset "arr[$(printf "%q" "$key")]" 
$ declare -p arr 
declare -A arr='([foo]="bar")' 
Problemi correlati