Why is echo foo | read a ; echo $a not working as expected?
Due to the piping the read
is executed in its own subshell.
echo foo | while read a; do echo $a; done
will do what you expect it to.
Why echo EOF not working as expected
You want:
cat <<EOF
abc
EOF
Otherwise, what you're doing is just running echo
with its stdin connected to a temporary file having abc
in it. Since echo
doesn't read stdin, it never finds out if there's contents waiting to be read from there or not.
I just assigned a variable, but echo $variable shows something else
In all of the cases above, the variable is correctly set, but not correctly read! The right way is to use double quotes when referencing:
echo "$var"
This gives the expected value in all the examples given. Always quote variable references!
Why?
When a variable is unquoted, it will:
Undergo field splitting where the value is split into multiple words on whitespace (by default):
Before:
/* Foobar is free software */
After:
/*
,Foobar
,is
,free
,software
,*/
Each of these words will undergo pathname expansion, where patterns are expanded into matching files:
Before:
/*
After:
/bin
,/boot
,/dev
,/etc
,/home
, ...Finally, all the arguments are passed to echo, which writes them out separated by single spaces, giving
/bin /boot /dev /etc /home Foobar is free software Desktop/ Downloads/
instead of the variable's value.
When the variable is quoted it will:
- Be substituted for its value.
- There is no step 2.
This is why you should always quote all variable references, unless you specifically require word splitting and pathname expansion. Tools like shellcheck are there to help, and will warn about missing quotes in all the cases above.
tee command not working as expected (with read and echo)
read -p
is writing it's output to stderr
and echo
is writing to stdout
. stdout
is typically buffered while stderr
is not, and so it's not uncommon to see stderr
things show up before stdout
.
You could have your echo
also go to stderr
if you like by doing echo "string" >&2
or you could run it in the unbuffer
command or similar tools if you have them available
bash shell builtin read not working as expected
Pipes create a subshell, and a variable created in a subshell does not exist in the main environment.
You can do:
$ read line < <(echo 'my text')
$ echo "$line"
my text
Bash -n argument not recognized by script when using $@
The -n
or -e
are valid options for the echo
command.
Therefore it's consumed by the echo command and only the remaining text is shown.
That's a known problem of echo
and to avoid this you can use printf
.
printf "%s\n" "$*"
Why does the read command in bash work with a herestring but not with piped output?
The read
works, but you need to ask for the values in the same subshell:
echo "1 2 3" | (read -r one two three && echo "one: $one, two: $two, three: $three")
An alternative is
read -r one two three < <( echo "1 2 3")
Related Topics
Sh: 0: Getcwd() Failed: No Such File or Directory on Cited Drive
How to Figure Out What Is Using a Linux Kernel Module
Bpf Verifier Rejects Code: "Invalid Bpf_Context Access"
What Are Good Linux/Unix Books for an Advancing User
Bash Pass Variable as Argument with Quotes
Why Does Find -Exec Mv {} ./Target/ + Not Work
Selecting a Linux I/O Scheduler
How to Find Words from One File in Another File
How to Get the List of Dependent Child Images in Docker
How to Create a Statically Linked Position Independent Executable Elf in Linux
What Is the Meaning of Each Line of the Assembly Output of a C Hello World
Get a Substring from a File Shell Script
Linux Kernel Device Driver to Dma from a Device into User-Space Memory
How to Filter Data Between 2 Dates with Awk in a Bash Script