readarray (nebo pipe) problém

Zachoval jsem se podivným chováním příkazu readarray.

Stavy man bash:

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

, ale tyto skripty nefungují (pole je prázdné):

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

A tyto práce:

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 je s potrubím špatně?

Odpověď

Možná zkuste:

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

Očekávám, že to bude fungovat , ale v okamžiku, kdy vystoupíte z posledního { prostředí ; } kontextu na konci | pipeline tam ztratíte hodnotu proměnné. Je to proto, že každý z | samostatných | procesů v rámci | kanálu je spuštěn v a ( subshell ). Vaše věc tedy nefunguje ze stejného důvodu:

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

… nefunguje – hodnota proměnné byla nastavena v jiném shell proces než ten, ve kterém na něj zavoláte.

Odpovědět

Zajistit readarray příkaz se provádí v aktuálním prostředí, buď použijte místo potrubí nahrazení procesu:

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

nebo (pokud bash 4.2 nebo novější) použijte lastpipe možnost prostředí:

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

Komentáře

  • Super. To funguje, ale co přesně je substituce procesu? A co to znamená mít < < 2 šipky?
  • Podívejte se na bash manuálovou stránku. Stručně řečeno, je to ' syntaxe pro zpracování kanálu jako deskriptoru souboru. < <(...) znamená přesměrovat vstup (první <) z výstupu příkazu uvnitř <(...). Podobně by > >(...) předal standardní výstup na standardní vstup potrubí uvnitř >(...). ' nemusíte nutně používat přesměrování s nahrazením procesu. cat <( echo a b c ) funguje také.
  • Obě tyto možnosti vytvářejí pro mě nežádoucí výsledek, kdy každá položka pole zachovává konce řádků na konci každého řetězce. Zatímco odpověď smac89 tento problém nemá.
  • Konce řádků lze odstranit pomocí readarray -t arr. Z man bash: -t Remove a trailing newline from each line read.
  • I ' m pomocí bash 5.0.17 a to pro mě ' nefunguje. I ' jsem dokonce zkontroloval BASHOPTS a obsahuje lastpipe, přesto cat myfile.txt | readarray -t arr dává prázdný arr, ale readarray -t arr < <(cat myfile.txt) funguje správně.

Odpověď

readarray umí číst také ze stdin, takže:

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

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *