I've tried to break this down a little bit for you, using your own examples/text as well, check it out:
$ cat fred
#!/bin/bash
fred='Four spaces between these words.'
echo "The value of \$fred is $fred"
echo "The next line being printed is simply the results of # echo \$fred"
echo $fred
Running the bash script above prints the following to the terminal/stdout:
The value of $fred is Four spaces between these words.
The next line being printed is simply the results of # echo $fred
Four spaces between these words.
As well, you can view a terminal video of this here:
http://showterm.io/98f56243f60551b338b9f
:D I can't explain it!!! If you can understand what they are saying in Advanced Bash-Scripting Guide: Chapter 20. I/O Redirection, write a new answer and I will give you 50rep:
exec 3>&1;
result=$(dialog --inputbox test 0 0 2>&1 1>&3);
exitcode=$?;
exec 3>&-;
echo $result $exitcode;
Reference: Dialog in bash is not grabbing variables correctly
^ answer from @Sneetsher (Jul 4, 2014)
As requested, I will try to explain what this snippet is doing line by line.
Note that I will simplify it by omitting all the ;
semicolons at the line ends, because they're not necessary if we write one command per line.
I/O - Streams:
First, you need to understand the communication streams. There are 10 streams, numbered from 0 to 9:
Stream 0 ("STDIN"):
"Standard input", the default input stream to read data from the keyboard.
Stream 1 ("STDOUT"):
"Standard output", the default output stream used to show normal text in the terminal.
Stream 2 ("STDERR"):
"Standard error", the default output stream used to display errors or other text for special purposes in the terminal.
Streams 3-9:
Additional, freely usable streams. They're not used by default and do not exist until something attempts to use them.
Note that all "streams" are internally represented by file descriptors in /dev/fd
(which is a symbolic link to /proc/self/fd
which contains another symbolic link for every stream... it's a bit complicated and not important for their behaviour, so I stop here.). The standard streams also have /dev/stdin
, /dev/stdout
and /dev/stderr
(which are symbolic links again, etc...).
The script:
exec 3>&1
The Bash built-in exec
can be used to apply a stream redirection to the shell, that means it affects all following commands. For more info, run help exec
in your terminal.
In this special case, the stream 3 gets redirected to stream 1 (STDOUT), that means everything we send to stream 3 later will appear in our terminal as if it was normally printed to STDOUT.
result=$(dialog --inputbox test 0 0 2>&1 1>&3)
This line consists of many parts and syntactical structures:
result=$(...)
This structure executes the command in the brackets and assigns the output (STDOUT) to the bash variable result
. It's readable through $result
. All this is described somehow in the veeeery looong man bash
.
dialog --inputbox TEXT HEIGHT WIDTH
This command shows a TUI box with the given TEXT, a text input field and two buttons OK and CANCEL. If OK gets selected, the command exits with status 0 and prints the entered text to STDERR, if CANCEL gets selected, it will exit with code 1 and print nothing. For more info, read man dialog
.
2>&1 1>&3
These are two redirection commands. They will be interpreted from right to left:
1>&3
redirects the command's stream 1 (STDOUT) to the custom stream 3.
2>&1
redirects afterwards the command's stream 2 (STDERR) to stream 1 (STDOUT).
That means that everything the command prints to STDOUT now appears in stream 3, while everything that was intended to show up on STDERR now gets redirected to STDOUT.
So the entire line displays a text prompt (on STDOUT, which got redirected to stream 3, which the shell again redirects back to STDOUT in the end - see the exec 3>&1
command) and assigns the entered data (returned through STDERR, then redirected to STDOUT) to the Bash variable result
.
exitcode=$?
This code retrieves the previously executed command's exit code (here from dialog
) through the reserved Bash variable $?
(always holds the last exit code) and simply stores it in our own Bash variable exitcode
. It can be read through $exitcode
again. You can search for more info on this in man bash
, but that might take a while...
exec 3>&-
The Bash built-in exec
can be used to apply a stream redirection to the shell, that means it affects all following commands. For more info, run help exec
in your terminal.
In this special case, the stream 3 gets redirected to "stream -", which just means it should be closed. Data sent to stream 3 will not get redirected anywhere any more from now on.
echo $result $exitcode
This simple echo
command (more info on man echo
) just prints the content of the two Bash variables result
and exitcode
to the STDOUT. As we have no explicit or implicit stream redirections here any more, they will really appear on STDOUT and therefore simply get displayed in the terminal. What a miracle! ;-)
Summary:
First, we set the shell up to redirect everything we send to the custom stream 3 back to STDOUT, so that it shows up in our terminal.
Then we run the dialog
command, redirect its original STDOUT to our custom stream 3, because it needs to get displayed in the end, but we temporarily need to use the STDOUT stream for something else.
We redirect the original STDERR of the command, where the dialogue window's user input gets returned, to STDOUT afterwards.
Now we can capture the STDOUT (which holds the redirected data from STDERR) and store it in our variable $result
. It contains the wanted user input now!
We also want the dialog
command's exit code, which shows us whether OK or CANCEL was clicked. This value is presented in the reserved Bash variable $?
and we just copy it to our own variable $exitcode
.
After that we close stream 3 again, as we don't need it any more, to stop further redirections of it.
Finally, we normally output the contents of both variables $result
(the user input of the dialogue window) and $exitcode
(0 for OK, 1 for CANCEL) to the terminal.
Best Answer
In bash, you can add
-n 3
or-N 3
depending on the exact behavior you require. Fromhelp read
: