2016-06-14 24 views
6

W Bash, chcę usunąć ustawienie hashmap. Ale mi się nie udało. Kod jest następujący:Bash hashmap za pomocą cytatu jako klucz

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 

Jak mogę usunąć ten wpis?

+0

['unset arr [" $ key "]'] (http://mywiki.wooledge.org/BashGuide/Practices#Quoting)? ** EDYTUJ **: To też nie działa ... – anishsane

+1

Wygląda jak błąd w bashu – Leon

+0

Hmm ... moje złe ... Również, 'arr ['$ x'] = 123; unset arr ['$ x'] 'daje' -bash: unset: [$ x]: bad array subscript' – anishsane

Odpowiedz

5

Wystarczy użyć apostrofów:

$ 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")' 

Gotowe!

+0

genialny sposób! – ruanhao

+1

To jest magiczne. Czy udokumentowano, że "unset" wykonuje drugą rundę ekspansji? –

+0

@glennjackman: Nie widziałem, żeby to było naprawdę udokumentowane, ale nie jest specyficzne dla 'unset'. Arytmetyczny kontekst pokazuje również to zachowanie: 'declare -A glenn; key = '$ (ls> &2)'; ((glenn [$ key])). Niespodzianka, odpowiedź prawdopodobnie znajduje się w źródle ':)'. Bash ma naprawdę szalony sposób analizowania danych. –

4

Tricky. Można to zrobić ręcznie przez ucieczce „wewnętrzny” jeden cytat:

$ 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")' 

Ale jak to zrobić „programowo”? Na szczęście bash ma mechanizm "ucieczki" ciąg: 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")'