what is wrong with my unix script

后端 未结 5 1022
温柔的废话
温柔的废话 2021-01-29 03:17
#!/bin/bash

while echo -n \"Player\'s name?\"
    read name
    [ $name != \'ZZZ\' ]
do
    searchresult=$(grep [$name] playername)
    if [ $searchresult = 0 ]
    the         


        
相关标签:
5条回答
  • 2021-01-29 03:22

    grep returns multiple words so shell interprets the if statement as having so many tokens. If you just want to check if there was a match, do this:

    if grep "$name" playername &> /dev/null; then
        # ....
    
    0 讨论(0)
  • 2021-01-29 03:24

    Quote the variable name:

    "$searchresult"
    

    Also, youa have other failures in the script.

    • remove brackets from the greps if you do not need them
    • rewrite the condition in while
    0 讨论(0)
  • 2021-01-29 03:26

    It would REALLY HELP if you include a sample of the data in the three files you're using 'grep' on!

    You've misunderstood what the

    variable=$(command)
    

    operation does. The '$()' operation assigns the standard output of the command to the variable, not the exit code of the command. If you want to use your original script, with the exit code, try this instead:

    grep [$name] playername > /dev/null 2>&1
    searchresult=$?
    

    The '=' operator in 'test' (also known as '[ ]') is for strings. You really want to use the '-eq' operator instead, which is for integers.

    Without the data, I can't really figure out what the rest of the script should look like. As it is, it really looks strange to me.

    Since you're using bash, I can make a suggestion for improving your input checking.

    target=UnSeT
    while [ $target = "UnSeT" ]
    do
        read -p "if See target (T/t) or team name (M/m)?" target
        case "$target" in
            [Tt]) target="T";;
            [Mm]) target="M";;
            *) target="UnSeT"; echo "Please enter T or M.";;
        esac
    done
    
    0 讨论(0)
  • 2021-01-29 03:31

    Use -eq instead = in your if statement in your script or use -z option to check empty string.

    0 讨论(0)
  • 2021-01-29 03:42

    There are multiple things wrong with your script. The most egregious problem is that you need to quote your variables.

    For example, if $name contained a value with a space, you get weird results:

    name='a value'
    grep [$name] file
    

    would end up grepping for [a (which isn't a valid regex) in value] (which almost certainly doesn't exist).

    Quoting fixes that, but the use of [...] in grep is also weird. For example,

    name='abc'
    grep "[$name]" file
    

    will find in file any line which contains a anywhere in it, or b anywhere in it, or c anywhere in it. This can hardly be what you want.

    If your intention is to search for a literal string,

    grep -F "$name" file
    

    does that.

    Here is an attempt to rewrite your script more idiomatically.

    #!/bin/sh
    
    while true; do
        read -p "Player's name? " name
        case $name in "ZZZ" | "") break ;; esac
        if grep -F -q "$name" playername; then
            # Not sure what the logic should be here?
            while true; do
                read -p "See target (T/t) or team name (M/m)? " choice
                case $choice in
                    [Tt]) file=targetselected; break ;;
                    [Mm]) file=teamselected; break ;;
                esac
                echo "Only enter T/t or M/m.  Try again."
            done
            grep -F "$name" "$file"
        else
            echo 'no such player'
        fi
    done
    

    There is nothing Bash-specific in this script, so I changed the shebang line to /bin/sh.

    However, the logic seems awkward. I am imagining your players file would look something like this:

    Maisy
    Tallulah
    Cyril
    Eddie
    

    and the teams something like

    Tallulah,Chickens,Astronauts
    Maisy,Obnoxity,Fallacious
    Cyril,Rodents
    Eddie,Dirt,False,Breakfast of Champions
    

    then if you search for "all" you would find "Tallulah" in the first file, but print both Maisy and Tallulah from the teams file because they both contain the text "all" somewhere on the line. It would be better to simply search the team or target file directly, perhaps using Awk instead of grep:

    awk -F, -v q="$1" '$1 ~ q' "$file"
    

    and if there was no output, the player didn't exist in the first place.

    As you grow more familiar with the Unix shell, you will want to avoid tools which force an interactive dialog. Instead, you might want to have a simple tool like this:

    #!/bin/sh
    file=players
    while true; do
        case $1 in
            -[Tt]) shift; file=targetselected;;
            -[Mm]) shift; file=teamselected;;
            *) break;;
        esac
    done
    awk -F, -v q="$1" '$1 ~ q' "$file"
    

    which is easy to use as a component in a larger script, easy to recall from your command history, easy to add not one but many different GUIs around if you really need one, and (once you get used to it) easy to use.

    0 讨论(0)
提交回复
热议问题