in bash, read after a pipe is not setting values
Edit : original title was "read fails in bash"
With ksh I'm using read as a convenient way to separate values:
$ echo 1 2 3 4 5 | read a b dump
$ echo $b $a
2 1
$
But it fails in bash :
$ echo 1 2 3 4 5 | read a b dump
$ echo $b $a
$
I didn't find a reason in the man page why it fails, any idea ?
bash shell pipe read
add a comment |
Edit : original title was "read fails in bash"
With ksh I'm using read as a convenient way to separate values:
$ echo 1 2 3 4 5 | read a b dump
$ echo $b $a
2 1
$
But it fails in bash :
$ echo 1 2 3 4 5 | read a b dump
$ echo $b $a
$
I didn't find a reason in the man page why it fails, any idea ?
bash shell pipe read
1
This is discussed (somewhat obscurely) in page 024 of Greg’s Bash FAQ.
– Scott
Jul 11 '14 at 18:27
add a comment |
Edit : original title was "read fails in bash"
With ksh I'm using read as a convenient way to separate values:
$ echo 1 2 3 4 5 | read a b dump
$ echo $b $a
2 1
$
But it fails in bash :
$ echo 1 2 3 4 5 | read a b dump
$ echo $b $a
$
I didn't find a reason in the man page why it fails, any idea ?
bash shell pipe read
Edit : original title was "read fails in bash"
With ksh I'm using read as a convenient way to separate values:
$ echo 1 2 3 4 5 | read a b dump
$ echo $b $a
2 1
$
But it fails in bash :
$ echo 1 2 3 4 5 | read a b dump
$ echo $b $a
$
I didn't find a reason in the man page why it fails, any idea ?
bash shell pipe read
bash shell pipe read
edited Oct 21 '18 at 10:52
Gilles
534k12810741594
534k12810741594
asked Jul 11 '14 at 10:34
EmmanuelEmmanuel
3,03411120
3,03411120
1
This is discussed (somewhat obscurely) in page 024 of Greg’s Bash FAQ.
– Scott
Jul 11 '14 at 18:27
add a comment |
1
This is discussed (somewhat obscurely) in page 024 of Greg’s Bash FAQ.
– Scott
Jul 11 '14 at 18:27
1
1
This is discussed (somewhat obscurely) in page 024 of Greg’s Bash FAQ.
– Scott
Jul 11 '14 at 18:27
This is discussed (somewhat obscurely) in page 024 of Greg’s Bash FAQ.
– Scott
Jul 11 '14 at 18:27
add a comment |
2 Answers
2
active
oldest
votes
bash
runs the right-hand side of a pipeline in a subshell context, so changes to variables (which is what read
does) are not preserved — they die when the subshell does, at the end of the command.
Instead, you can use process substitution:
$ read a b dump < <(echo 1 2 3 4 5)
$ echo $b $a
2 1
In this case, read
is running within our primary shell, and our output-producing command runs in the subshell. The <(...)
syntax creates a subshell and connects its output to a pipe, which we redirect into the input of read
with the ordinary <
operation. Because read
ran in our main shell the variables are set correctly.
As pointed out in a comment, if your goal is literally to split a string into variables somehow, you can use a here string:
read a b dump <<<"1 2 3 4 5"
I assume there's more to it than that, but this is a better option if there isn't.
3
Or evenread a b dump <<< '1 2 3 4 5'
.
– choroba
Jul 11 '14 at 10:41
Thank you to all, btw I noted that mksh (on cygwin) is doing the same as bash.
– Emmanuel
Jul 11 '14 at 10:56
@Michael Homer Good explanation! I found another one example that can explain that every command in pipeline run in own subshell:cat /etc/passwd | (read -r line ; echo $line)
. But nextecho
of$line
which is not in pipeline put nothing on screen, because value was existed just between parentheses (subshell) . Hope, It helps someone.
– Yurij Goncharuk
May 3 '18 at 10:28
add a comment |
This is not a bash
bug as POSIX
allows both bash
and ksh
behaviors, leading to the unfortunate discrepancy you are observing.
http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_12
Additionally, each command of a multi-command pipeline is in a subshell environment; as an extension, however, any or all commands in a pipeline may be executed in the current environment. All other commands shall be executed in the current shell environment.
However, with bash 4.2
and newer, you can set the lastpipe
option in non interactive scripts to get the expected result, eg:
#!/bin/bash
echo 1 2 3 4 5 | read a b dump
echo before: $b $a
shopt -s lastpipe
echo 1 2 3 4 5 | read a b dump
echo after: $b $a
Output:
before:
after: 2 1
1
+1 thank you for the "lastpipe" info. sorry for the delay
– Emmanuel
Jul 29 '14 at 14:47
1
the problem withlastpipe
is that it doesn't work in other shells (e.g. dash). there's basically no way to do this portable short of running everything in that subshell, see stackoverflow.com/questions/36268479/…
– anarcat
Feb 8 '17 at 15:46
1
@anarcat This is correct but the question asked here was about bash.
– jlliagre
Feb 8 '17 at 15:49
@anarcat: This may change in the future since there is a wish to change POSIX for another reason (PIPE Status) see here: unix.stackexchange.com/questions/476834/… Changing other shells is not trivial, it took me several months to rewrite the parser and interpeter on the Bourne Shell (bosh) to implement the faster behavior of the modern ksh.
– schily
Oct 21 '18 at 13:42
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "106"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f143958%2fin-bash-read-after-a-pipe-is-not-setting-values%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
bash
runs the right-hand side of a pipeline in a subshell context, so changes to variables (which is what read
does) are not preserved — they die when the subshell does, at the end of the command.
Instead, you can use process substitution:
$ read a b dump < <(echo 1 2 3 4 5)
$ echo $b $a
2 1
In this case, read
is running within our primary shell, and our output-producing command runs in the subshell. The <(...)
syntax creates a subshell and connects its output to a pipe, which we redirect into the input of read
with the ordinary <
operation. Because read
ran in our main shell the variables are set correctly.
As pointed out in a comment, if your goal is literally to split a string into variables somehow, you can use a here string:
read a b dump <<<"1 2 3 4 5"
I assume there's more to it than that, but this is a better option if there isn't.
3
Or evenread a b dump <<< '1 2 3 4 5'
.
– choroba
Jul 11 '14 at 10:41
Thank you to all, btw I noted that mksh (on cygwin) is doing the same as bash.
– Emmanuel
Jul 11 '14 at 10:56
@Michael Homer Good explanation! I found another one example that can explain that every command in pipeline run in own subshell:cat /etc/passwd | (read -r line ; echo $line)
. But nextecho
of$line
which is not in pipeline put nothing on screen, because value was existed just between parentheses (subshell) . Hope, It helps someone.
– Yurij Goncharuk
May 3 '18 at 10:28
add a comment |
bash
runs the right-hand side of a pipeline in a subshell context, so changes to variables (which is what read
does) are not preserved — they die when the subshell does, at the end of the command.
Instead, you can use process substitution:
$ read a b dump < <(echo 1 2 3 4 5)
$ echo $b $a
2 1
In this case, read
is running within our primary shell, and our output-producing command runs in the subshell. The <(...)
syntax creates a subshell and connects its output to a pipe, which we redirect into the input of read
with the ordinary <
operation. Because read
ran in our main shell the variables are set correctly.
As pointed out in a comment, if your goal is literally to split a string into variables somehow, you can use a here string:
read a b dump <<<"1 2 3 4 5"
I assume there's more to it than that, but this is a better option if there isn't.
3
Or evenread a b dump <<< '1 2 3 4 5'
.
– choroba
Jul 11 '14 at 10:41
Thank you to all, btw I noted that mksh (on cygwin) is doing the same as bash.
– Emmanuel
Jul 11 '14 at 10:56
@Michael Homer Good explanation! I found another one example that can explain that every command in pipeline run in own subshell:cat /etc/passwd | (read -r line ; echo $line)
. But nextecho
of$line
which is not in pipeline put nothing on screen, because value was existed just between parentheses (subshell) . Hope, It helps someone.
– Yurij Goncharuk
May 3 '18 at 10:28
add a comment |
bash
runs the right-hand side of a pipeline in a subshell context, so changes to variables (which is what read
does) are not preserved — they die when the subshell does, at the end of the command.
Instead, you can use process substitution:
$ read a b dump < <(echo 1 2 3 4 5)
$ echo $b $a
2 1
In this case, read
is running within our primary shell, and our output-producing command runs in the subshell. The <(...)
syntax creates a subshell and connects its output to a pipe, which we redirect into the input of read
with the ordinary <
operation. Because read
ran in our main shell the variables are set correctly.
As pointed out in a comment, if your goal is literally to split a string into variables somehow, you can use a here string:
read a b dump <<<"1 2 3 4 5"
I assume there's more to it than that, but this is a better option if there isn't.
bash
runs the right-hand side of a pipeline in a subshell context, so changes to variables (which is what read
does) are not preserved — they die when the subshell does, at the end of the command.
Instead, you can use process substitution:
$ read a b dump < <(echo 1 2 3 4 5)
$ echo $b $a
2 1
In this case, read
is running within our primary shell, and our output-producing command runs in the subshell. The <(...)
syntax creates a subshell and connects its output to a pipe, which we redirect into the input of read
with the ordinary <
operation. Because read
ran in our main shell the variables are set correctly.
As pointed out in a comment, if your goal is literally to split a string into variables somehow, you can use a here string:
read a b dump <<<"1 2 3 4 5"
I assume there's more to it than that, but this is a better option if there isn't.
answered Jul 11 '14 at 10:40
Michael HomerMichael Homer
47.3k8124162
47.3k8124162
3
Or evenread a b dump <<< '1 2 3 4 5'
.
– choroba
Jul 11 '14 at 10:41
Thank you to all, btw I noted that mksh (on cygwin) is doing the same as bash.
– Emmanuel
Jul 11 '14 at 10:56
@Michael Homer Good explanation! I found another one example that can explain that every command in pipeline run in own subshell:cat /etc/passwd | (read -r line ; echo $line)
. But nextecho
of$line
which is not in pipeline put nothing on screen, because value was existed just between parentheses (subshell) . Hope, It helps someone.
– Yurij Goncharuk
May 3 '18 at 10:28
add a comment |
3
Or evenread a b dump <<< '1 2 3 4 5'
.
– choroba
Jul 11 '14 at 10:41
Thank you to all, btw I noted that mksh (on cygwin) is doing the same as bash.
– Emmanuel
Jul 11 '14 at 10:56
@Michael Homer Good explanation! I found another one example that can explain that every command in pipeline run in own subshell:cat /etc/passwd | (read -r line ; echo $line)
. But nextecho
of$line
which is not in pipeline put nothing on screen, because value was existed just between parentheses (subshell) . Hope, It helps someone.
– Yurij Goncharuk
May 3 '18 at 10:28
3
3
Or even
read a b dump <<< '1 2 3 4 5'
.– choroba
Jul 11 '14 at 10:41
Or even
read a b dump <<< '1 2 3 4 5'
.– choroba
Jul 11 '14 at 10:41
Thank you to all, btw I noted that mksh (on cygwin) is doing the same as bash.
– Emmanuel
Jul 11 '14 at 10:56
Thank you to all, btw I noted that mksh (on cygwin) is doing the same as bash.
– Emmanuel
Jul 11 '14 at 10:56
@Michael Homer Good explanation! I found another one example that can explain that every command in pipeline run in own subshell:
cat /etc/passwd | (read -r line ; echo $line)
. But next echo
of $line
which is not in pipeline put nothing on screen, because value was existed just between parentheses (subshell) . Hope, It helps someone.– Yurij Goncharuk
May 3 '18 at 10:28
@Michael Homer Good explanation! I found another one example that can explain that every command in pipeline run in own subshell:
cat /etc/passwd | (read -r line ; echo $line)
. But next echo
of $line
which is not in pipeline put nothing on screen, because value was existed just between parentheses (subshell) . Hope, It helps someone.– Yurij Goncharuk
May 3 '18 at 10:28
add a comment |
This is not a bash
bug as POSIX
allows both bash
and ksh
behaviors, leading to the unfortunate discrepancy you are observing.
http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_12
Additionally, each command of a multi-command pipeline is in a subshell environment; as an extension, however, any or all commands in a pipeline may be executed in the current environment. All other commands shall be executed in the current shell environment.
However, with bash 4.2
and newer, you can set the lastpipe
option in non interactive scripts to get the expected result, eg:
#!/bin/bash
echo 1 2 3 4 5 | read a b dump
echo before: $b $a
shopt -s lastpipe
echo 1 2 3 4 5 | read a b dump
echo after: $b $a
Output:
before:
after: 2 1
1
+1 thank you for the "lastpipe" info. sorry for the delay
– Emmanuel
Jul 29 '14 at 14:47
1
the problem withlastpipe
is that it doesn't work in other shells (e.g. dash). there's basically no way to do this portable short of running everything in that subshell, see stackoverflow.com/questions/36268479/…
– anarcat
Feb 8 '17 at 15:46
1
@anarcat This is correct but the question asked here was about bash.
– jlliagre
Feb 8 '17 at 15:49
@anarcat: This may change in the future since there is a wish to change POSIX for another reason (PIPE Status) see here: unix.stackexchange.com/questions/476834/… Changing other shells is not trivial, it took me several months to rewrite the parser and interpeter on the Bourne Shell (bosh) to implement the faster behavior of the modern ksh.
– schily
Oct 21 '18 at 13:42
add a comment |
This is not a bash
bug as POSIX
allows both bash
and ksh
behaviors, leading to the unfortunate discrepancy you are observing.
http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_12
Additionally, each command of a multi-command pipeline is in a subshell environment; as an extension, however, any or all commands in a pipeline may be executed in the current environment. All other commands shall be executed in the current shell environment.
However, with bash 4.2
and newer, you can set the lastpipe
option in non interactive scripts to get the expected result, eg:
#!/bin/bash
echo 1 2 3 4 5 | read a b dump
echo before: $b $a
shopt -s lastpipe
echo 1 2 3 4 5 | read a b dump
echo after: $b $a
Output:
before:
after: 2 1
1
+1 thank you for the "lastpipe" info. sorry for the delay
– Emmanuel
Jul 29 '14 at 14:47
1
the problem withlastpipe
is that it doesn't work in other shells (e.g. dash). there's basically no way to do this portable short of running everything in that subshell, see stackoverflow.com/questions/36268479/…
– anarcat
Feb 8 '17 at 15:46
1
@anarcat This is correct but the question asked here was about bash.
– jlliagre
Feb 8 '17 at 15:49
@anarcat: This may change in the future since there is a wish to change POSIX for another reason (PIPE Status) see here: unix.stackexchange.com/questions/476834/… Changing other shells is not trivial, it took me several months to rewrite the parser and interpeter on the Bourne Shell (bosh) to implement the faster behavior of the modern ksh.
– schily
Oct 21 '18 at 13:42
add a comment |
This is not a bash
bug as POSIX
allows both bash
and ksh
behaviors, leading to the unfortunate discrepancy you are observing.
http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_12
Additionally, each command of a multi-command pipeline is in a subshell environment; as an extension, however, any or all commands in a pipeline may be executed in the current environment. All other commands shall be executed in the current shell environment.
However, with bash 4.2
and newer, you can set the lastpipe
option in non interactive scripts to get the expected result, eg:
#!/bin/bash
echo 1 2 3 4 5 | read a b dump
echo before: $b $a
shopt -s lastpipe
echo 1 2 3 4 5 | read a b dump
echo after: $b $a
Output:
before:
after: 2 1
This is not a bash
bug as POSIX
allows both bash
and ksh
behaviors, leading to the unfortunate discrepancy you are observing.
http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_12
Additionally, each command of a multi-command pipeline is in a subshell environment; as an extension, however, any or all commands in a pipeline may be executed in the current environment. All other commands shall be executed in the current shell environment.
However, with bash 4.2
and newer, you can set the lastpipe
option in non interactive scripts to get the expected result, eg:
#!/bin/bash
echo 1 2 3 4 5 | read a b dump
echo before: $b $a
shopt -s lastpipe
echo 1 2 3 4 5 | read a b dump
echo after: $b $a
Output:
before:
after: 2 1
edited Jul 12 '14 at 9:25
answered Jul 12 '14 at 9:18
jlliagrejlliagre
46.9k783133
46.9k783133
1
+1 thank you for the "lastpipe" info. sorry for the delay
– Emmanuel
Jul 29 '14 at 14:47
1
the problem withlastpipe
is that it doesn't work in other shells (e.g. dash). there's basically no way to do this portable short of running everything in that subshell, see stackoverflow.com/questions/36268479/…
– anarcat
Feb 8 '17 at 15:46
1
@anarcat This is correct but the question asked here was about bash.
– jlliagre
Feb 8 '17 at 15:49
@anarcat: This may change in the future since there is a wish to change POSIX for another reason (PIPE Status) see here: unix.stackexchange.com/questions/476834/… Changing other shells is not trivial, it took me several months to rewrite the parser and interpeter on the Bourne Shell (bosh) to implement the faster behavior of the modern ksh.
– schily
Oct 21 '18 at 13:42
add a comment |
1
+1 thank you for the "lastpipe" info. sorry for the delay
– Emmanuel
Jul 29 '14 at 14:47
1
the problem withlastpipe
is that it doesn't work in other shells (e.g. dash). there's basically no way to do this portable short of running everything in that subshell, see stackoverflow.com/questions/36268479/…
– anarcat
Feb 8 '17 at 15:46
1
@anarcat This is correct but the question asked here was about bash.
– jlliagre
Feb 8 '17 at 15:49
@anarcat: This may change in the future since there is a wish to change POSIX for another reason (PIPE Status) see here: unix.stackexchange.com/questions/476834/… Changing other shells is not trivial, it took me several months to rewrite the parser and interpeter on the Bourne Shell (bosh) to implement the faster behavior of the modern ksh.
– schily
Oct 21 '18 at 13:42
1
1
+1 thank you for the "lastpipe" info. sorry for the delay
– Emmanuel
Jul 29 '14 at 14:47
+1 thank you for the "lastpipe" info. sorry for the delay
– Emmanuel
Jul 29 '14 at 14:47
1
1
the problem with
lastpipe
is that it doesn't work in other shells (e.g. dash). there's basically no way to do this portable short of running everything in that subshell, see stackoverflow.com/questions/36268479/…– anarcat
Feb 8 '17 at 15:46
the problem with
lastpipe
is that it doesn't work in other shells (e.g. dash). there's basically no way to do this portable short of running everything in that subshell, see stackoverflow.com/questions/36268479/…– anarcat
Feb 8 '17 at 15:46
1
1
@anarcat This is correct but the question asked here was about bash.
– jlliagre
Feb 8 '17 at 15:49
@anarcat This is correct but the question asked here was about bash.
– jlliagre
Feb 8 '17 at 15:49
@anarcat: This may change in the future since there is a wish to change POSIX for another reason (PIPE Status) see here: unix.stackexchange.com/questions/476834/… Changing other shells is not trivial, it took me several months to rewrite the parser and interpeter on the Bourne Shell (bosh) to implement the faster behavior of the modern ksh.
– schily
Oct 21 '18 at 13:42
@anarcat: This may change in the future since there is a wish to change POSIX for another reason (PIPE Status) see here: unix.stackexchange.com/questions/476834/… Changing other shells is not trivial, it took me several months to rewrite the parser and interpeter on the Bourne Shell (bosh) to implement the faster behavior of the modern ksh.
– schily
Oct 21 '18 at 13:42
add a comment |
Thanks for contributing an answer to Unix & Linux Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f143958%2fin-bash-read-after-a-pipe-is-not-setting-values%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
This is discussed (somewhat obscurely) in page 024 of Greg’s Bash FAQ.
– Scott
Jul 11 '14 at 18:27