3

I want to query the function by returning the value. My codes are as follows;

check(){
    file=/root/Turkiye.txt
    local funkx=$1
    while read line; do
        if [ "$line" == "$funkx" ]
        then
            true
            break
        else
            false
        fi
    done < $file
}

printf "Please enter the value : "
read keyboard

if check $keyboard;
then
    echo "yes";
else
    echo "no";
fi

It does not work, what am I doing wrong?

  • The only problems I found with your code that it prints an error message if the file does not exist and that it prints yes if the file is empty. – Bodo Feb 28 at 9:51
5

true and false are commands that exit with success and failure exit codes, respectively. They do not make your function return those values, to do that use the return command, and integer values corresponding to success (0) or failure (anything other than 0). Also, I'm pretty sure you don't want to return failure for the first line that doesn't match, just if no line matched:

check(){
    file=/root/Turkiye.txt
    local funkx=$1
    while read line; do
        if [ "$line" == "$funkx" ]
        then
            return 0    # 0 = success ("true"); break is not needed because return exits the function
        fi
    done < $file
    # If a line matched, it won't get here (it will have returned out of the middle
    # of the loop). Therefore, if it gets here, there must not have been a match.
    return 1    # 1 = failure ("false")
}

But there's a much simpler way to do this. Use grep -- its job is to search files for matching lines. You want grep -Fxq -- -F means search for fixed strings (not regular expression patterns), -x means require the whole line to match, not just part of it, and -q means don't bother printing the result, just exit with success status if a match was found, failure otherwise. And you don't even need an explicit return command, since the function will implicitly return the status of the last command in it:

check(){
    file=/root/Turkiye.txt
    local funkx=$1
    grep -Fxq "$funkx" "$file"
}

Or even simpler:

check(){
    grep -Fxq "$1" /root/Turkiye.txt
}
  • Technically true; return and false; return work: return defaults to the last exit code $? – D. Ben Knoble Feb 28 at 15:44
  • 1
    @D.BenKnoble You're correct, but the original script does something much less obvious than that. In fact, you could remove the true and false commands (or reverse them) in the original script and it wouldn't change the results. That's because if a line matches, it executes true, and then break, so the return status is from the break command (which will be 0). Similarly, if no match is found the last command executed is the loop test, read line (which will be 1). So it actually gets the right results, but not for reasonable reasons. – Gordon Davisson Feb 28 at 23:01
3

Testing your code on another file, it does actually work, even if it's a bit inefficient. Assuming that the /root/Turkiye.txt file is a non-empty file that you have access to, the true and false calls, since they are the last commands to be executed in the function, sets the exit status of the function to either zero or non-zero.

It may simply be that you are entering strings into your script that can't be found as separate lines in the file you are reading. It's unfortunately unclear in the question what the file you are parsing looks like, what you are entering into your script and what you expect to get as a response from the script when doing so.

Note also that while read line does not necessarily read lines from the input file. See e.g. "Understanding "IFS= read -r line"", and also that within [ ... ] the operator that compares two strings is =, not ==.

You also need to double quote $keyboard in your call to check to avoid word splitting and filename generation (globbing).


It seems as if you want to use your function to determine whether the string read from the user occurs as a line in a particular file.

This could be done easier with

grep -qxF -e "$keyboard" /root/Turkiye.txt

This grep command would search for the string in the given file and return a zero exit status (true) if a line is found that is exactly identical, and will otherwise return a non-zero exit status (false). The options used here are -q to make grep not output anything, -x to compare full lines (not substrings) and -F to do string comparisons (not regular expression matching). The -e tells grep that the next argument is the search pattern (an initial - in the pattern would otherwise have been taken as introducing a command line option).

Your script, modified:

printf 'Please enter the value: ' >&2
IFS= read -r keyboard

if grep -qxF -e "$keyboard" /root/Turkiye.txt; then
    echo 'yes'
else
    echo 'no'
fi

Note that I output the prompt for the user to enter a string to the standard error stream. This is by convention and allows the output of the script to be redirected and used without it containing the prompt.

In bash, you would have used

IFS= read -r -p 'Please enter the value: ' keyboard

(Note that bash would output the prompt string to the standard error stream too when you use read -p.)

If you would want to use the grep in a function:

check () {
    grep -qxF -e "$1" /root/Turkiye.txt
}

Then use

if check "$keyboard"; then
    echo 'yes'
else
    echo 'no'
fi

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.