readarray (eller pipe) udgave

Jeg sidder fast med en underlig opførsel af readarray kommando.

man bash siger:

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

men disse scripts fungerer ikke (arrayet er tomt):

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

Hvad er der galt med rør?

Svar

Måske prøve:

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

Jeg forventer, at det vil fungere , men det øjeblik du træder ud af den sidste { shell ; } kontekst i slutningen af | pipeline der mister du din variable værdi. Dette skyldes, at hver af | separate | processer inden for en | pipeline udføres i en ( subshell ). Så din ting virker ikke af samme grund:

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

… virker ikke – variabelværdien blev indstillet i en anden shell-proces end den, du kalder på den.

Svar

At sikre readarray kommando udføres i den aktuelle shell, brug enten proceserstatning i stedet for pipelinen:

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

eller (hvis bash 4.2 eller nyere) brug lastpipe shell-indstillingen:

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

Kommentarer

  • Cool. Dette fungerer, men hvad er egentlig proceserstatning? Og hvad betyder det at have < < 2 pile?
  • Se bash man-siden. Kort sagt er det ' s syntaks til behandling af en pipeline som en filbeskrivelse. < <(...) betyder at omdirigere input (den første <) fra output af kommandoen inde i <(...). Tilsvarende ville > >(...) sende standardoutput til standardindgangen på rørledningen inde i >(...). Du behøver ikke ' nødvendigvis bruge omdirigering med proceserstatning. cat <( echo a b c ) fungerer også.
  • Begge disse muligheder giver et uønsket resultat for mig, hvor hvert array-element bevarer linieenderne i slutningen af hver streng. Mens svaret fra smac89 ikke har dette problem.
  • Linjeendelser kan fjernes ved hjælp af readarray -t arr. Fra man bash: -t Remove a trailing newline from each line read.
  • I ' m ved hjælp af bash 5.0.17 og dette fungerer ikke ' for mig. Jeg ' har endda tjekket BASHOPTS og den indeholder lastpipe, alligevel cat myfile.txt | readarray -t arr giver en tom arr, men readarray -t arr < <(cat myfile.txt) fungerer korrekt.

Svar

readarray kan også læses fra stdin, så:

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

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *