readarray (eller pipe) utgave

Jeg holdt fast med en merkelig oppførsel av readarray kommando.

man bash sier:

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

men disse skriptene fungerer ikke (matrisen er tom):

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

Og disse fungerer:

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

Hva er galt med pipe?

Svar

Kanskje prøv:

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

Jeg forventer at det vil fungere , men i det øyeblikket du går ut av den siste { shell ; } kontekst på slutten av | rørledning der mister du variabelverdien. Dette er fordi hver av | separate | prosesser i en | -rørledning utføres i en ( subshell ). Så din ting fungerer ikke av samme grunn:

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

… virker ikke – variabelverdien ble satt i en annen skallprosess enn den du ringer på.

Svar

For å sikre readarray kommandoen kjøres i det nåværende skallet, enten bruk prosessubstitusjon i stedet for rørledningen:

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

eller (hvis bash 4.2 eller nyere) bruk lastpipe skallalternativ:

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

Kommentarer

  • Kult. Dette fungerer, men hva er egentlig prosessubstitusjon? Og hva betyr det å ha < < 2 piler?
  • Se bash man-siden. Kort fortalt er det ' syntaksen for å behandle en rørledning som en filbeskrivelse. < <(...) betyr å omdirigere inngang (den første <) fra utgangen av kommandoen i <(...). I likhet med > >(...) vil standardutgang sendes til standardinngangen til rørledningen inne i >(...). Du trenger ikke ' ikke nødvendigvis bruke omdirigering med prosessubstitusjon. cat <( echo a b c ) fungerer også.
  • Begge disse alternativene gir et uønsket resultat for meg, der hvert matriseelement beholder linjeendene på slutten av hver streng. Mens svaret fra smac89 ikke har dette problemet.
  • Linjeendinger kan fjernes ved hjelp av readarray -t arr. Fra man bash: -t Remove a trailing newline from each line read.
  • I ' m ved hjelp av bash 5.0.17 og dette fungerer ikke ' for meg. Jeg ' har til og med sjekket BASHOPTS og den inneholder lastpipe, men cat myfile.txt | readarray -t arr gir en tom arr, men readarray -t arr < <(cat myfile.txt) fungerer riktig.

Svar

readarray kan også leses fra stdin, så:

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

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert. Obligatoriske felt er merket med *