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.

if [ ! -z $1 ]
    while read line
        if [ $update == $line ]
            echo "yes";

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?

  • 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 3:53

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

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.