Answer-ID
  • Întrebări
  • Tag-uri
  • Categorii
Notificări
Recompense
Înregistrare
După înregistrare, veți primi notificări despre răspunsurile și comentariile la întrebările DVS.
Logare
Dacă aveţi deja un cont, autentificaţi-vă pentru a verifica notificările noi.
Aici vor fi recompensele pentru întrebările, răspunsurile și comentariile adăugate sau modificate.
Mai mult
Sursă
Editează
Ryan Ahearn
Ryan Ahearn

Shell scripting intrări de redirecționare ciudățenii

Poate cineva să explice acest comportament? Alergare:

#!/bin/sh
echo "hello world" | read var1 var2
echo $var1
echo $var2

nu are ca rezultat nimic, în timp ce:

#!/bin/sh
echo "hello world" > test.file
read var1 var2 < test.file
echo $var1
echo $var2

produce rezultatul așteptat:

hello
world

Nu ar trebui ca conducta să facă într-un singur pas ce a făcut redirecționarea către test.file în al doilea exemplu? Am încercat același cod cu ambele cochilii de bord și bash și am primit același comportament de la amândouă.

18 2008-08-05T19:26:00+00:00 7
Programare
linux
shell
bash
ksh
dash-shell
Comentarii la întrebare (0)
Mark Harrison
1 ianuarie 1970 в 3:00
1970-01-01T03:00:00+00:00
Mai mult
Sursă
Editează
#2764

Este pentru că versiunea conductei creează un subshell, care citește variabila în spațiul său local, care este distrus atunci când subshell-ul iese.

Executați această comandă

$ echo $$;cat | read a
10637

și folosiți pstree -p pentru a vă uita la procesele care rulează, veți vedea o cochilie extra agățată de cochilia dvs. principală.

    |                       |-bash(10637)-+-bash(10786)
    |                       |             `-cat(10785)
0
0
Comentarii (0)
num1
1 ianuarie 1970 в 3:00
1970-01-01T03:00:00+00:00
Mai mult
Sursă
Editează
#2777

Bine, mi-am dat seama!

Acesta este un bug greu de capturat, dar rezultă din modul în care conductele sunt manipulate de cochilie. Fiecare element al unei conducte se desfășoară într-un proces separat. Când comanda read stabilește var1 și var2, le stabilește propriile subshell-uri, nu shell-ul parental. Deci, atunci când subshell-ul iese, valorile var1 și var2 sunt pierdute. Cu toate acestea, puteți încerca să faceți

var1=$(echo "Hello")
echo var1

care returnează răspunsul așteptat. Din păcate, acest lucru funcționează numai pentru variabilele unice, nu puteți seta multe la un moment dat. Pentru a seta mai multe variabile la un moment dat, trebuie fie să citiți într-o singură variabilă și să o introduceți în mai multe variabile sau să folosiți ceva de genul:

set -- $(echo "Hello World")
var1="$1" var2="$2"
echo $var1
echo $var2

În timp ce recunosc că nu este la fel de elegant ca utilizarea unei țevi, funcționează. Desigur, ar trebui să rețineți că citirea a fost menită să citească din fișiere în variabile, astfel încât a face citirea de la standard de intrare ar trebui să fie un pic mai greu.

0
0
Comentarii (0)
Jon Ericson
1 ianuarie 1970 в 3:00
1970-01-01T03:00:00+00:00
Mai mult
Sursă
Editează
#12412

Acest lucru a fost deja corect răspuns, dar soluția nu a fost încă stabilită. Utilizați ksh, nu bash. Comparaţie:

$ echo 'echo "hello world" | read var1 var2
echo $var1
echo $var2' | bash -s

La:

$ echo 'echo "hello world" | read var1 var2
echo $var1
echo $var2' | ksh -s
hello
world

ksh este o coajă de programare superioară din cauza unor mici priceperi ca aceasta. (bash este cea mai bună coajă interactivă, în opinia mea.)

0
0
Comentarii (0)
Utilizator anonim
1 ianuarie 1970 в 3:00
1970-01-01T03:00:00+00:00
Mai mult
Sursă
Editează
#61462

Postul a primit un răspuns corect, dar aș dori să ofer o altă linie de transport care ar putea fi de folos.

Pentru a atribui valori separate de spațiu de la ecou (sau stdout pentru acel lucru) la variabilele shell, puteți lua în considerare utilizarea matricelor coajă:

$ var=( $( echo 'hello world' ) )
$ echo ${var[0]}
hello
$ echo ${var[1]}
world

În acest exemplu, var este o matrice și conținutul poate fi accesat folosind structura $ {var [index]}, unde indexul este indexul matricei (începe cu 0).

În acest fel puteți avea cât mai mulți parametri pe care doriți să li se atribuie indexului de matrice relevant.

0
0
Comentarii (0)
Steve Baker
1 ianuarie 1970 в 3:00
1970-01-01T03:00:00+00:00
Mai mult
Sursă
Editează
#78604
read var1 var2 < <(echo "hello world")
0
0
Comentarii (0)
pjz
1 ianuarie 1970 в 3:00
1970-01-01T03:00:00+00:00
Mai mult
Sursă
Editează
#79203

Încerca:

echo "hello world" | (read var1 var2 ; echo $var1 ; echo $var2 )

Problema, așa cum au declarat mai mulți oameni, este că var1 și var2 sunt create într-un mediu subshell care este distrus când acel subshell iese. Cele de mai sus evită distrugerea subsalvei până când rezultatul a fost ecou. O altă soluție este:

result=`echo "hello world"`
read var1 var2 <
0
0
Comentarii (0)
flabdablet
1 ianuarie 1970 в 3:00
1970-01-01T03:00:00+00:00
Mai mult
Sursă
Editează
#98945
#!/bin/sh
echo "hello world" | read var1 var2
echo $var1
echo $var2

nu produce nici o ieșire, deoarece conductele rulează fiecare dintre componentele lor într-un subshell. Subshell-uri moștenește copii din variabilele shell-ului părinte, mai degrabă decât să le partajați. Incearca asta:

#!/bin/sh
foo="contents of shell variable foo"
echo $foo
(
    echo $foo
    foo="foo contents modified"
    echo $foo
)
echo $foo

Parantezele definesc o regiune de cod care se execută într-un subshell și $ foo își păstrează valoarea inițială după ce a fost modificată în interiorul lor.

Încearcă acum:

#!/bin/sh
foo="contents of shell variable foo"
echo $foo
{
    echo $foo
    foo="foo contents modified"
    echo $foo
}
echo $foo

Plăcile sunt doar pentru grupare, nu se creează un subshell și $ foo modificat în interiorul bretelelor este același $ foo modificat în afara lor.

Încearcă acum:

#!/bin/sh
echo "hello world" | {
    read var1 var2
    echo $var1
    echo $var2
}
echo $var1
echo $var2

În interiorul bretelelor, cititul încorporat creează în mod corespunzător $ var1 și $ var2 și puteți vedea că ele sunt reluate. În afara bretelelor, ele nu mai există. Tot codul din bretele a fost rulat într-un subshell deoarece este o componentă a unei conducte .

Aveți posibilitatea să puneți cantități arbitrare de cod între acolade, astfel încât să puteți utiliza această construcție de conducte în blocuri ori de câte ori aveți nevoie pentru a rula un bloc de script shell care analizează rezultatul altceva.

0
0
Comentarii (0)
Utilizator anonim
1 ianuarie 1970 в 3:00
1970-01-01T03:00:00+00:00
Mai mult
Sursă
Editează
#609915

Mă ocup de această problemă (folosind Bash):

read var1 var2 <<< "hello world"
echo $var1 $var2
0
0
Comentarii (0)
chepner
1 ianuarie 1970 в 3:00
1970-01-01T03:00:00+00:00
Mai mult
Sursă
Editează
#11668996

O adăugare recentă a bash este opțiunea lastpipe , care permite ultima comandă dintr-o conductă să ruleze în shell-ul curent, nu într-un subshell, atunci când controlul funcției este dezactivat.

#!/bin/bash
set +m      # Deactiveate job control
shopt -s lastpipe
echo "hello world" | read var1 var2
echo $var1
echo $var2

va ieși într-adevăr

hello
world
0
0
Comentarii (0)
Adăugati o întrebare
Categorii
Toate
Tehnologii
Cultură
Viață / Artă
Stiință
Profesii
Afaceri
ID
KO
RU
© Answer-ID 2021
Sursă
https://stackoverflow.com
în cadrul licenței cc by-sa 3.0 cu atribuire