Utwórz tablicę asocjacyjną z danych wyjściowych dwóch poleceń

Próbuję utworzyć katalogi użytkowników na podstawie zaimportowanego pliku passwd i próbuję załadować dane do tablica asocjacyjna: tablica [nazwa użytkownika] = katalog. Mogę załadować pola do oddzielnych tablic, ale nie mogę uzyskać poprawnych skojarzeń, ponieważ każde pole jest powiązane ze wszystkimi katalogami.

USERLIST=$(cat /usrmkr/in.out | awk -F ":" "{print $1}") DIRLIST=$(cat /usrmkr/in.out | awk -F ":" "{print $6}") declare -A USERARRAY func_StoreData() { USERARRAY[$1]="$2" return $? } for ((u=0;u<${USERLIST[@]};u++)); do func_StoreData ${USERLIST[$u]} ${DIRLIST[$u]} done for i in ${!USERARRAY[@]}; do echo "making directory for $i in ${USERARRAY[$i]}" #Do stuff done 

Komentarze

  • Jeśli którakolwiek z istniejących odpowiedzi rozwiąże Twój problem, rozważ zaakceptowanie go przez znacznik wyboru. Dziękuję!

Odpowiedź

Całość można przeczytać bezpośrednio za pomocą basha, nakazując read, aby podzielić na dwukropki :

declare -A userarray while IFS=: read -r username password uid gid gecos home shell; do userarray[$username]=$home done < /usrmkr/in.out 

Odpowiedź

 eval declare -A USERARRAY=( $(awk -F: "{ printf "[\"%s\"]=\"%s\"\n", $1, $6}" /usrmkr/in.out) )  

Skrypt awk generuje dane wyjściowe w formacie [key]=val wymagane przy ustawianiu wielu elementów tablicy asocjacyjnej basha i cudzysłowach zarówno klucz, jak i wartość (["key"]="value") w przypadku, gdy w kluczach lub wartościach występują spacje, tabulatory itp. .

Użyłem \n jako separatora, aby ułatwić przetwarzanie końcowe awk wyjście za pomocą innego narzędzia (chociaż awk i tak może zrobić większość rzeczy, które zechcesz zrobić z innymi narzędziami).

Zastępowanie poleceń powinno samo wystarczyć .. .ale z powodu tego, co to jest, IMO, błąd w bash, jeśli pierwszy znak niebędący białymi znakami wewnątrz ( ... ) definicji tablicy to „n” ta [, po prostu generuje komunikat o błędzie must use subscript when assigning associative array.

np. obie poniższe próby ustawienia USERARRAY zakończą się niepowodzeniem:

 $ bash --version | head -1 GNU bash, version 4.3.46(1)-release (x86_64-pc-linux-gnu) $ declare -A USERARRAY=($(awk -F: "{ printf "[\"%s\"]=\"%s\"\n", $1, $6}" /usrmkr/in.out)) bash: USERARRAY: $(awk -F: "{ printf "[\"%s\"]=\"%s\"\n", $1, $6}" /usrmkr/in.out): must use subscript when assigning associative array $ UA=$(awk -F: "{ printf "[\"%s\"]=\"%s\"\n", $1, $6}" /usrmkr/in.out) $ declare -A USERARRAY=( $UA ) bash: USERARRAY: $UA: must use subscript when assigning associative array  

Rozwiązaniem jest aby użyć eval podczas deklarowania tablicy zahaszowanej, jak w przykładzie kodu u góry mojej odpowiedzi. Lub

eval declare -A USERARRY=( $UA ) 

Komentarze

  • 1. wykorzystuje to eval – oczywiście istnieje ' ryzyko wstrzyknięcia polecenia. Nie ' nie sądzę, że ' jest problemem w tym przypadku, ponieważ moja odpowiedź jest przeznaczona do użycia z OP ' specyficzny & plik wejściowy prawdopodobnie sprawdzony / znany-dobry. 2. " zapomniałeś zacytować rozszerzenia " – co? co? Nie ' nie widzę żadnego problemu z cytowaniem – kod awk jawnie cytuje klucze i wartości tablicy. 3. BTW, prawie 2 lata później, bash v4.4.19 (1) -release nadal nie ' nie pozwala na bezpośrednie użycie polecenia cmd-subst, a nawet zmienna w deklaracji skrótu: declare -A array=( $(...) ) kończy się niepowodzeniem z tym samym błędem, więc eval jest nadal wymagany.
  • @St é phaneChazelas Jeśli występuje ' problem z cytowaniem, wyjaśnij, jak i dlaczego – najlepiej na przykładzie ze świata rzeczywistego, używając poprawnych danych wejściowych w stylu / etc / passwd, co ma znaczenie dla tego pytania i odpowiedzi, nie tylko ogólne i oczywiste ", jeśli wprowadzisz śmieciowe dane, ' uzyskasz nieprzewidywalne i potencjalnie niebezpieczne wyniki ".
  • ' masz wrażenie, że zazwyczaj nie stanowi to problemu dla typowego /etc/passwd dane. Pozwólcie, że przeformułuję to: ⚠ chociaż powinno być w porządku dla typowych danych /etc/passwd, to podejście nie powinno być stosowane w przypadku dowolnych danych, ponieważ stanowiłoby to lukę umożliwiającą wstrzyknięcie poleceń. W szczególności zakłada się, że dane nie ' nie zawierają, `, ", ukośnik odwrotny, $, *, ?, [, spacja lub znaki NUL.
  • O problemie z cytowaniem, zobacz na przykład Konsekwencje dla bezpieczeństwa zapomnienia o cytowaniu zmiennej w powłokach bash / POSIX oraz powiązane tam pytania, aby zobaczyć, co to znaczy pozostawić rozszerzenia bez cytowania.
  • Zauważ, że starsze wersje basha miały błąd, w którym ' a = (" $ x ") `nie utworzyłby tablicy z jednym elementem będącym zawartością $x kiedy $x było czymś w rodzaju [123]=qwe (to było przed tablicami asocjacyjnymi obsługiwanymi przez bash).To ' prawdziwy bash mógł pozwolić na zadeklarowanie tablic asocjacyjnych jako a=("$x") (gdzie $x musi zaczynać się od [...]=) oprócz składni a=([$k]=$v), ale wtedy musiałby zdefiniować sposób określenia klucze zawierające] znaków. W każdym razie nie nazwałbym tego błędem, ale decyzją projektową (tutaj podjęta przez ksh, skąd bash skopiował swoją składnię).

Odpowiedź

Zamiast łączyć dwie listy, możemy zbudować tablicę w pojedynczej pętli (i jednym wywołaniu awk dla dokładności), zwracając listę użytkowników: dir wpisów, a następnie podzielenie ich na różne rozszerzenia:

#!/bin/bash declare -A USERARRAY for u in $(awk -F: "{print $1 ":" $6}" /usrmkr/in.out) do user=${u%:*} dir=${u#*:} USERARRAY[$user]=$dir done 

Odpowiedź

zsh ma bardziej przydatne, bardziej typowe (podobne do tcl lub perl) sposób na zadeklarowanie tablic asocjacyjnych jako całości: array=(key1 value1 key2 value2...)

typeset -A userarray IFS=$":\n\n" userarray=($(cut -d : -f 1,6 < /usrmkr/in.out)) 

Podwojenie \n, jak w ksh93, usuwa specjalny status nowej linii jako znak IFS-biały znak . Bez niego foo:\nbar:x zostanie podzielony na „foo”, „bar”, „x” zamiast „foo”, „”, „bar”, „x”.

Z , składnia jest taka sama, jak w ksh93: array=([key1]=value1 [key2]=value2), więc nie można łatwo uzyskać wyniku polecenia do tablicy asocjacyjnej w inny sposób niż przy użyciu pętli wykonującej przypisanie pojedynczego elementu naraz, jak pokazały inne.

Zauważ, że bash tablice asocjacyjne ( w przeciwieństwie do ksh93 lub zsh) mają ograniczenie polegające na tym, że klucz nie może być pustym ciągiem (nie jest to problem). Kolejnym ograniczeniem, tym razem dzielonym z ksh93, jest to, że ani klucz, ani wartości nie mogą zawierać bajtu NUL (również nie jest to problem).

(obsługa tablic asocjacyjnych była w ksh93 od początku (1993), dodany do zsh w 1998 (3.1.5-pws-3) i bash w 2009 ( 4.0))

Komentarze

  • Dlaczego wstawiłeś ' \ n ' dwa razy do IFS?
  • @rubystallion zobacz edytuj

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *