-1

I have a few lines code. I just want to check if argument $1 is in the file with a while loop so I write this code.

#!/bin/bash
if [ ! -z $1 ]
then
    update=$1;
    while read line
    do
        if [ $update == $line ]
        then
            echo "yes";
        fi
    done<./available_updates
fi

But in debugging if I run

[root@pc bagheri]# bash -x ./test.sh my_value

it says:

+ '[' my_value == 'my_value' ']'

and jump over that condition just because of these two single quotes and not printing the 'yes' word, but I am 100% sure that the my_value is existed in available_updates file. What should I do for that?

AdminBee
  • 22,803
Mahdi
  • 19
  • 1
    Try quoting all your variables, for instance "$update" == "$line", because if you don't $line can expand into multiple strings instead of one. – SparedWhisle Jul 19 '20 at 12:54
  • 1
    What version of bash are you running? I can't reproduce what you're seeing with version 3.2, 4.0, 4.2, 4.3, 4.4, 5.0 – glenn jackman Jul 19 '20 at 13:40
  • Is "my_value" the actual value involved? In not, what is the actual value? – Gordon Davisson Jul 19 '20 at 17:12
  • 1
    @Mahdi, if $update and $line contain only my_value, the set -x output from the shell will not quote it. Above, you say that the output has no quotes around the first my_value but there are quotes around the second. Is that right? Are you sure that's the exact output? Because the presence of quotes there indicates the value has some special characters, other than letters and the underscore, but your output doesn't show them. Please [edit] to clarify. – ilkkachu Jul 19 '20 at 18:26
  • @glenn-jackman GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu) – Mahdi Jul 20 '20 at 03:53
  • Gordon Davisson, the actual value is roundcube – Mahdi Jul 20 '20 at 03:54
  • Reduce the file available_updates to just one line which triggers the problem and add the output of od -t c -t x1 available_updates to your question. – Hauke Laging Jul 22 '20 at 02:12

1 Answers1

1

Don't use shell loops to process text

#! /bin/sh -
update="${1?missing update argument}"
grep -Fxqe "$update" < available_updates && echo yes

Some of the problems in your code:

  • parameter expansions must be quoted in Bourne-like shells.
  • the syntax to read a line with read is IFS= read -r line, not read line.
  • The syntax to check that a script is given at least one argument if [ "$#" -gt 0 ] (though see also the ${1?error message} approach). [ ! -z "$1" ] (here adding the missing quotes) only check whether the first one is non-empty.

The ' you see in the xtrace output are not part of the data passed to the [ command, they are output there to make sure what's displayed constitutes valid shell code. That suggests $line doesn't contain just my_value there, but possibly some other invisible character as well which bash thinks need quoted. It could possibly be something like a U+FEFF, the "byte-order-mark" character.

Running LC_ALL=C sed -n l < available-updates could help reveal those invisible characters.

  • Additionally, the double "==" comparison is bashism, POSIX sh expects single "=". – Tomasz Pala Jul 19 '20 at 15:46
  • @TomaszPala, true == is not POSIX. Rather a kshism, but here the she-bang has #!/bin/bash so we're outside POSIX realm. – Stéphane Chazelas Jul 19 '20 at 15:47
  • OP calls bash, but this answer refers to sh - I'm just going to bring out that, apart from being absolutely not suitable for any kind of text processing, bash nor it's syntax is not standard way to write portable scripts (especially when they are being "ported" by changing she-bang line only). – Tomasz Pala Jul 19 '20 at 15:56