problem z tablicą odczytową (lub potokiem)

19

Utknąłem z dziwnym zachowaniem readarraydowodzenia.

Te man bashstany:

readarray
     Read lines from the standard input into the indexed array variable array

ale te skrypty nie działają (tablica jest pusta):

unset arr; (echo a; echo b; echo c) | readarray arr; echo ${#arr[@]}
unset arr; cat /etc/passwd | readarray arr;  echo ${#arr[@]}

A te działają:

unset arr; readarray arr < /etc/passwd ;  echo ${#arr[@]}
unset arr; mkfifo /tmp/fifo; (echo a; echo b; echo c) > /tmp/fifo & mapfile arr < /tmp/fifo ; echo ${#arr[@]}

Co złego dzieje się z fajką?

dchirikov
źródło

Odpowiedzi:

15

Może spróbuj:

unset arr
printf %s\\n a b c | {
    readarray arr
    echo ${#arr[@]}
}

Oczekuję, że to zadziała, ale gdy wyjdziesz z tego ostatniego kontekstu {powłoki ; }na końcu |potoku, stracisz swoją zmienną wartość. Wynika to z faktu, że każdy z |oddzielnych |procesów w |potoku jest wykonywany w (podpowłoce ). Twoja rzecz nie działa z tego samego powodu:

( arr=( a b c ) ) ; echo ${arr[@]}

... nie robi - wartość zmiennej została ustawiona w innym procesie powłoki niż ten, w którym ją wywołujesz.

mikeserv
źródło
23

Aby mieć pewność, że readarraypolecenie zostanie wykonane w bieżącej powłoce, użyj zastępowania procesu zamiast potoku:

readarray arr < <( echo a; echo b; echo c )

lub (jeśli bash4.2 lub nowszy) użyj lastpipeopcji powłoki:

shopt -s lastpipe
( echo a; echo b; echo c ) | readarray arr
chepner
źródło
1
Chłodny. To działa, ale czym dokładnie jest podstawienie procesu? A co to znaczy mieć < <2 strzały?
CMCDragonkai
1
Zobacz bashstronę manuala. Krótko mówiąc, jest to składnia do traktowania potoku jako deskryptora pliku. < <(...)oznacza przekierowanie wejścia (pierwszego <) z wyjścia polecenia wewnątrz <(...). Podobnie, > >(...)przekaże standardowe wyjście do standardowego wejścia rurociągu wewnątrz >(...). Niekoniecznie musisz używać przekierowania z substytucją procesu. cat <( echo a b c )działa również.
chepner
Obie te opcje dają mi niepożądany wynik, w którym każdy element tablicy zachowuje zakończenia linii na końcu każdego łańcucha. Podczas gdy odpowiedź smac89 nie ma tego problemu.
wtorek
3

readarray można również czytać ze standardowego wejścia, więc:

readarray arr <<< "$(echo a; echo b; echo c)"; echo ${#arr[@]}
smac89
źródło