问题
I'm writing a script that functions as a "talking terminal" (you type in commands and it says the output) and so far my code is:
#!/bin/bash
while [ 1=1 ]; do
echo -n "~>"
read COMMAND
espeak "$($COMMAND)"
done
and it works for simple commands:
bash$ ./talkingterminal.sh
~> ls
# espeak says "talkingterminal.sh"
but when I use pipes etc:
bash$ ./talkingterminal.sh
~>ip addr | grep inet
Command "|" is unknown, try "ip addr help".
~>
and that command works in bash and gives the expected output. any help? thanks, Martin
回答1:
This is a rare case where eval
is appropriate; you just putting a thin wrapper around what is already unlimited access to the command line. More importantly, you aren't modifying COMMAND
in any unexpected ways. What the user types is what will be executed.
#!/bin/bash
while : ; do
IFS= read -rp "~> " COMMAND
espeak "$(eval "$COMMAND")"
done
A few notes:
- The
read
builtin inbash
can display a custom prompt using the-p
option. - Use the
:
ortrue
commands, which always succeed, to set up an infinite loop. - Use the
-r
option and an empty value forIFS
to ensure thatCOMMAND
is set to the exact line typed by the user. - Quote
$COMMAND
so that the entire string is passed toeval
without any previous shell parsing. - Note that this still cannot handle multi-line input in the same fashion as the shell itself. (For example, a line like
for x in 1 2 3; do
will not prompt you for the body of the loop.)
回答2:
A simple solution is to use eval
:
#!/bin/bash
while [ 1=1 ]; do
echo -n "~>"
read COMMAND
espeak "$(eval $COMMAND)"
done
Then you can print output to the shell as well easily:
#!/bin/bash
while [ 1=1 ]; do
echo -n "~>"
read COMMAND
OUTPUT="$(eval $COMMAND)"
echo $OUTPUT
espeak "$($OUTPUT)"
done
回答3:
Have you tried to use the "-r" option? This option avoids interpreting special characters. Additionally you have to remove the external $() in the line:
espeak "$($COMMAND)"
It should be:
espeak "$(COMMAND)"
来源:https://stackoverflow.com/questions/32824972/running-a-command-that-is-stored-in-a-variable-including-pipes-and-redirects