简体   繁体   中英

Bash:Else not working in if/else statement in case statement

I am trying to check if a user types multiple arguments in a command line using case and if/else statements. What's wrong is that I keep getting the default case instead of the same command, but with 2 more arguments. For instance, one of my conditions is:

del)
    if [ -z "$2" ] || [ -z "$3" ]
    then
            echo "Usage: removes a file"
    else
    echo "using Bash command: rm $2 $3"
    rm $2 $3
    echo done
    fi

prints the first condition, but if I type, say, del aaa bbb, I get the default case, which is:

echo "ERROR: Unrecognized command"

I'm also using this to read a user's input, if that helps.

read -p "wcl> " -r wcl $2 $3

I don't really know if there's a better way to solve this without scrapping all my code and starting from scratch. This is the full code:

#!/bin/bash
#use read command

echo Welcome to the Windows Command Line simulator!
echo Enter your commands below
while true
do
read -p "wcl> " -r wcl $2 $3
    case  $wcl  in
     dir)
    echo "using Bash command: ls  $2 $3"
    ls
    continue 
            ;;
    copy)
    FILE="$2"
    if [ "$#" -ne 3 ]
    then
         echo "Usage: copy sourcefile destinationfile"
    else
    echo "using Bash command: cp $2 $3"
    if [ -f "$FILE" ]
    then
    cp $2 $3
    else
    echo "cannot stat $FILE: No such file or directory">&2
    fi
    echo done
    fi
    continue
            ;;
    del)
    if [ -z "$2" ] || [ -z "$3" ]
    then
            echo "Usage: removes a file"
    else
    echo "using Bash command: rm $2 $3"
    rm $2 $3
    echo done
    fi
    continue
            ;;
    move)
    if [ -z "$2" ] || [ -z "$3" ]
    then
            echo "Usage: moves a file to another file name and location"
    else
    echo "using Bash command: mv $2 $3"
    mv $2 $3
    echo done
    fi
    continue
            ;;
    rename)
    if [ -z "$2" ] || [ -z "$3" ]
    then
            echo "Usage: renames a file"
    else
    echo "using Bash command: mv $2 $3"
    mv $2 $3
    echo done
    fi
    continue
            ;;
    ipconfig)
            ifconfig eth0 | grep "inet addr" | cut -d ':' -f 2 | cut -d ' ' -f 1
    continue
            ;;
      exit)
            echo "Goodbye"
            exit 1
            ;;
    ^c)
            echo "Goodbye"
            exit 1
            ;;
*)
            echo "ERROR: Unrecognized command"
    continue
esac
done

You can't use read to set the positional parameters, although it isn't clear why you would need to here. Just use regular parameters.

while true
do
    read -p "wcl> " -r wcl arg1 arg2
    case  $wcl  in
     dir)
    echo "using Bash command: ls  $arg1 $arg2"
    ls "$arg1" "$arg2"
    continue 
            ;;

    # ...
    esac
done

The way read -r wcl $2 $3 is executed is that $2 and $3 are first expanded to give names that read will use to set variables. If those aren't set, then the command reduces to read -r wcl , and so your entire command line is assigned to the variable wcl , not just the command.

However, read by itself is not going to do the same parsing that the shell already does, if you goal is to write your own shell.

If you are really using bash, you can insert the words you read into positional parameters through an array. (You could also just leave them in the array, but the syntax for referring to positional parameters is simpler.)

# -a: read the successive words into an array
read -r -p "wcl> " -a params
# set the positional parameters to the expansion of the array
set -- "${params[@]}" 
wcl=$1  # Or you could do the case on "$1"

This will also set $# to the number of words read, as a side-effect of setting the positional parameters.

As @chepner points outs , the read is problematic: It simply splits the input into whitespace-separated words, without respecting quotes, backslashes, and whatever other shell metacharacters you might want to implement. Doing a full bash-style parse of a command-line in bash itself would be quite a difficult exercise.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM