I have a very short Bash script, like this:

variable="3 things"
if $(echo $variable|grep "^[0-9]\{1,\}") #if $variable begins with [0-9]
    echo $(echo $variable|sed 's/ .*$//')
    echo "0"

$variable will eventually be the output of a command which will be a string beginning with either a number or the word "No ". I want the script to return just the number or else the digit 0.

I'm getting the error, script.bash: line 2: 3: command not found and I don't understand why bash is trying to execute "3" as a command. Any insight would be appreciated (or suggestions on better ways to write this---I'm not good with bash script).


  • As an aside, your regex is either more complex or less complex than it needs to be. Just plain ^[0-9] will match every line that your ^[0-9]\{1,\} will match. Maybe you want to limit matches to those where a space follows the digits? If so, try ^[0-9]\{1,\} (note the trailing space). Apr 28, 2011 at 3:51

2 Answers 2


Try this:

variable="3 things"
if echo "$variable" | grep "^[0-9]\{1,\}" >/dev/null 2>&1 #if $variable begins with [0-9]
    echo "$variable" | sed 's/ .*$//'
    echo "0"

When using the $(...) notation, you are executing the inside command and placing it's output in it's place. The directive if runs the output of that and sees if it is successful. In this case, you really want to test the success of the command you put inside the $(...). It's also good to quote variables when used.

  • @penguin259: That works perfectly. I guess I got confused about how to use if vs $(...), and testing return values (basically I was trying to test whether grep returned anything or not). Thanks!
    – Wolf
    Apr 28, 2011 at 1:50
  • 1
    @Wolf, in that case, use grep -q .... Apr 28, 2011 at 2:38
  • @Glenn I used redirection as that is more portable. Some greps don't support -q or treat it as -s.
    – penguin359
    Apr 28, 2011 at 3:02
  • @Wolf Here's some more explanatin. A pipe is a type of complex COMMAND combining mutliple simple COMMANDs in a pipeline. When using multiple simple commands together in a pipe, the return status of the whole pipe is equal to the greatest return status of any individual simple command. Basically that means a pipe is only considered successful if every command was successful. The full syntax of if is if COMMAND1; then COMMAND2; ...; elif COMMAND3; then COMMAND4; ..; else COMMAND5; fi The ; can be replaced by a newline. Basically, if COMMAND1 is successful, COMMAND2 is executed an so on
    – penguin359
    Apr 28, 2011 at 3:08
  • nice answer, but this would be more readable: if [[ "$variable" =~ ^[0-9]\{1,\} ]]
    – Kim
    Apr 28, 2011 at 5:30

Your script is not trying to execute your variable.
It is trying to execute the output from 'grep'...
The reason it is attempting to execute 3, is for the same reason as when if command is encountered in the script.. The command's is run and its exit code is tested by if.. Your grep output presents if 3 to bash.

if command ;then do-something; fi is okay because if tests the exit code of command.
if 3 ; then do-somethin; fi will fail, because 3 isn't a command... Here is a simple example to indicate if command...

function error() { return 1 ; }
if error  ;then echo A-cond1 ; else echo A-cond2 ;fi
if echo -n;then echo B-cond1 ; else echo B-cond2 ;fi
# `if 3` fails as you already know..
# output:

You can easily avoid all that, and let 'sed' handle the condition tests and the output.

for var in \
  "3 things" \
  " 1 leading space" \
  "10 green bottles" \
  echo "$var" |sed -e "s/^\([0-9]\+\).*/\1/" \
                   -e "s/^[^0-9].*/0/"



This site is temporarily in read-only mode and not accepting new answers.

Not the answer you're looking for? Browse other questions tagged .