0

First of all, I have little experience using Bash and I apologize for my bad English. Maybe it's obvious.

I am trying to understand why Bash drop value of the variable in this oneliner.

echo "Alpha;Beta;Gamma" | IFS=";" read First Second Third; echo $First $Second $Third

no output

But

echo "Alpha;Beta;Gamma" | (IFS=";" read First Second Third; echo $First $Second $Third)

has the right output

Alpha Beta Gamma.

I guess the read command opens a subshell and when it is close the variables lose their values.

If I am right, how to prevent it?

The goal was to separate a CSV like structure into variables.

Thanks in advice!

BR,

b

ilkkachu
  • 138,973
bas1c
  • 1
  • Thank you for the hint! Partially yes, because there is no loop at all. And I expect that the last pipe will be executed in the parent shell, therefore the variables would be defined there and keep their value. – bas1c Jan 28 '24 at 18:12
  • In the meantime i dug up some info from this toppic link. This type of redirection is working while read var ; do x=55 ; done < <(echo fred) echo "$x". But I don't understand why. – bas1c Jan 28 '24 at 18:24
  • 1
    The last command in a pipeline is not executed in the parent shell (unless you set the lastpipe option -- but it's not set by default). Whether that last command is a while loop or a simple command like read does not matter. As for why the done < <(echo fred) version works, it's because that's not a pipe, so the while loop isn't forced into a subshell. – Gordon Davisson Jan 28 '24 at 19:02
  • "I guess the read command opens a subshell and when it is close the variables lose their values.", it's not read, but the pipeline. True, read is one to naturally appear in cases like this, but see Gilles' example of a=0; a=1 | a=2; echo $a in their answer to the while read question. – ilkkachu Jan 28 '24 at 20:03
  • @ilkkachu That is my problem exactly. The last part (right side of the pipe) lose the value. In the example it keeps it. That is what confuse me. – bas1c Jan 28 '24 at 21:09
  • @GordonDavisson I have tried with the lastpipe also, but the result was the same. – bas1c Jan 28 '24 at 21:09
  • @bas1c, the difference between a | b; c and a | (b; c) is that in the second one, the right-hand side of the pipeline contains the whole group in parenthesis. You can do that, but in some cases you might need to put basically the whole remainder of the script within that group, which might be a bit awkward. – ilkkachu Jan 29 '24 at 07:56
  • @bas1c Correction: you need to set lastpipe and disable job control, so run shopt -s lastpipe; set +m and then retry your test. – Gordon Davisson Jan 29 '24 at 09:30

0 Answers0