2
username="hello"
password="3333"

function login {
    # 1 - Username
    # 2 - Password
    match=0
    cat LoginsMaintMenu.txt | while read line; do
            x=`echo $line | awk '{print $1}'`
            y=`echo $line | awk '{print $2}'`
            if [ "${x}" == "${1}" ] && [ "${y}" == "${2}" ]; then
                    echo "match"
                    match=1
                    echo $match
                    break
            fi
    done
    echo $match
    return $match
}

echo $username $password
login ${username} ${password}
if [ $? -eq 0 ]; then
echo "FAIL"
else
echo "success"
fi

output:

hello 3333
match
1
0
FAIL

THE PROBLEM: I don't understand why it is echoing "fail". the "match" variable gets set to 1 inside the while loop, but for some reason once I am out of the while loop it still thinks it is the initial zero from its declaration.

I have tried doing a lot of different things, so if someone could give me something concrete to try that'd be great!

Thanks

3
  • the while read is executed in a sub-shell, so any modifications you make are not passed to the parent. One of the many annoyances of bash scripting. Commented Mar 13, 2013 at 16:18
  • @MikeWeller Since bash supports process substitution, a pipeline is never needed. Commented Mar 13, 2013 at 16:21
  • The convention is that a return value of 0 represents success, and non-zero represents failure. It is a very bad idea to ignore that convention. Commented Mar 13, 2013 at 21:12

2 Answers 2

8

The reason that this is not working is actually the UUOC. In bash, the right side of a pipeline is ran inside of a sub-shell. Any variables set inside of a sub shell will not be set in the parent shell. To fix this, use redirection instead of a pipeline:

username="hello"
password="3333"

function login {
    # 1 - Username
    # 2 - Password
    match=0
    while read x y _; do
        if [ "${x}" == "${1}" ] && [ "${y}" == "${2}" ]; then
            echo "match"
            match=1
            echo $match
            break
        fi
    done < LoginsMaintMenu.txt
    echo $match
    return $match
}

echo $username $password
if login "${username}" "${password}"; then
    echo "FAIL"
else
    echo "success"
fi
Sign up to request clarification or add additional context in comments.

2 Comments

@dan It puts the first field of the line in x, the second in y, and discards the rest of the line. It's the equivalent of the awk assignments in the question, without the need for awk.
Note that because the original code flaunts the convention of returning 0 for success, you should remove the ! in the if, or swap the strings FAIL and success.
2

The while read ... part of your code (that gets its input from the cat pipe) runs in a subshell. Changes to variables inside that are not visible outside that subshell.

To work around that, change your loop to:

while read ... ; do
  ...
done < LoginsMaintMenu.txt

2 Comments

I didn't know who posted first! so I gave accepted answer to the other guy cuz he has less points ;) Thanks a lot for answering though!
jordanm's answer is also more complete - it avoids your two awkward awks. You should certainly accept his answer (who posted first is unimportant).

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.