problema readarray (sau pipe)

Am rămas cu un comportament ciudat al comenzii readarray.

man bash afirmă:

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

dar aceste scripturi nu funcționează (matricea este goală):

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

Și acestea funcționează:

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[@]} 

Ce e în neregulă cu țeava?

Răspuns

Poate încercați:

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

Sper că va funcționa , dar în momentul în care ieși din ultimul context { shell ; } la sfârșitul contextului | pipeline acolo veți pierde valoarea variabilă. Acest lucru se datorează faptului că fiecare dintre procesele | separate | dintr-o conductă | este executat în o ( subshell ). Deci, lucrurile dvs. nu funcționează din același motiv:

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

… doesn „t – valoarea variabilei a fost setată într-un diferit proces shell decât cel în care îl apelați.

Răspuns

Pentru a asigura se execută în shell-ul curent, fie folosiți înlocuirea procesului în locul conductei:

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

sau (dacă bash 4.2 sau o versiune ulterioară) utilizați opțiunea shell lastpipe:

shopt -s lastpipe ( echo a; echo b; echo c ) | readarray -t arr 

Comentarii

  • Super. Acest lucru funcționează, dar ce este exact substituirea procesului? Și ce înseamnă să ai < < 2 săgeți?
  • Consultați pagina de manual bash. Pe scurt, ' este sintaxa pentru tratarea unei conducte ca descriptor de fișier. < <(...) înseamnă redirecționarea intrării (primul <) din ieșirea comenzii din <(...). În mod similar, > >(...) ar transmite ieșirea standard la intrarea standard a conductei din interiorul >(...). Nu ' nu trebuie neapărat să utilizați redirecționarea cu substituirea procesului. cat <( echo a b c ) funcționează, de asemenea.
  • Ambele opțiuni produc un rezultat nedorit pentru mine, în care fiecare element de matrice reține sfârșiturile de linie la sfârșitul fiecărui șir. În timp ce răspunsul de la smac89 nu are această problemă.
  • Terminațiile de linie pot fi eliminate folosind readarray -t arr. De la man bash: -t Remove a trailing newline from each line read.
  • I ' m folosind bash 5.0.17 și acest lucru nu funcționează pentru mine ' Am ' chiar verificat BASHOPTS și conține lastpipe, totuși cat myfile.txt | readarray -t arr dă un arr gol, dar readarray -t arr < <(cat myfile.txt) funcționează corect.

Răspuns

readarray poate citi și din stdin, deci:

readarray arr <<< "$(echo a; echo b; echo c)"; echo ${#arr[@]} 

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *