7

I'm currently writing a bash script that should check if the exact string 329, exists in myfile. I have searched through the web and found some answers, but I can't use -x parameters because I have more numbers than 329, on myfile. And without the -x parameter, I can get the Exists result with 329 too, which I don't want.

I tried;

if grep -xqFe "329," "myfile"; then
    echo -e "Exists"
else
    echo -e "Not Exists"
fi

And the output was;

Not Exists

Inside of myfile;

329, 2, 57

How can I solve this?

0

2 Answers 2

12

The -x isn't relevant here. That means (from man grep):

-x, --line-regexp
       Select  only  those  matches that exactly match the whole line.
       For a regular expression pattern, this is  like  parenthesizing
       the pattern and then surrounding it with ^ and $.

So it is only useful if you want to find lines that contain nothing other than the exact string you are looking for. The option you want is -w:

-w, --word-regexp
       Select  only  those  lines  containing  matches that form whole
       words.  The test is that the matching substring must either  be
       at  the  beginning  of  the  line,  or  preceded  by a non-word
       constituent character.  Similarly, it must be either at the end
       of  the  line  or followed by a non-word constituent character.
       Word-constituent  characters  are  letters,  digits,  and   the
       underscore.  This option has no effect if -x is also specified.

That will match if you find your target string as a standalone "word", as a string surrounded by "non-word" characters. You also don't need the -F here, that is only useful if your pattern contains characters with special meanings in regular expressions which you want to find literally (e.g. *), and you don't need -e at all, that would be needed if you wanted to give more than one pattern. So you're looking for:

if grep -wq "329," myfile; then 
    echo "Exists" 
else 
    echo "Does not exist"
fi

If you also want to match when the number is the last one on the line, so it has no , after it, you can use grep -E to enable extended regular expressions and then match either a 329 followed by a comma (329,) or a 329 that is at the end of the line (329$). You can combine those like this:

if grep -Ewq "329(,|$)" myfile; then 
    echo "Exists" 
else 
    echo "Does not exist"
fi
9
  • Is -F not likely to be faster? Though I did read that one (the most common?) grep implementation can detect some fixed-strings and optimize for them Aug 6, 2022 at 23:28
  • 3
    @D.BenKnoble the -F would only work for the first example, not the second, and given that there are no special regex characters there and we're just searching for a simple string, I doubt it would be any faster. And indeed, I tested with a 2.6G file with one occurrence of 329, in the middle of 80 million lines of other stuff. I ran grep -F 329, and grep 329, ten times each and took the average. They both took 0.33 seconds, no significant difference at all.
    – terdon
    Aug 7, 2022 at 11:57
  • 1
    @D.BenKnoble you still need to read from disk. That will most likely drown cpu usage. Aug 7, 2022 at 19:35
  • @ThorbjørnRavnAndersen Disk reads is not really a solid argument when it comes to text processing and grep … It will most likely almost certainly not drown CPU usage … Please, have a look at speed tests in my answer here where grep outperforms other text processing tools even when it reads the same huge file multiple times with even less CPU usage time.
    – Raffa
    Aug 7, 2022 at 21:01
  • @raffa Interesting. How did you ensure Linux didn't cache file.dat in memory? Aug 8, 2022 at 17:06
-1

Another alternative might be :

if cat myfile | tr "," "\n" | grep -xqF "329"; then
    echo -e "Exists"
else
    echo -e "Not Exists"
fi

Regards

5
  • 5
    Isn't that a useless use of cat?
    – gidds
    Aug 6, 2022 at 21:23
  • @gidds It's a major award.
    – MDeBusk
    Aug 7, 2022 at 2:55
  • @gidds there are bigger fish to fry… Aug 7, 2022 at 19:36
  • The only way to provide input to tr is standard input, and the input specified in the question is in a file : how can you achieve it using a simpler method than cat ? Aug 8, 2022 at 7:35
  • 2
    Input redirection from the file directly. tr "," "\n" < myfile. Or if you prefer, <myfile tr ... | grep. Other than that inefficiency though, I like the idea of turning , into newline so the last element is no longer special, although note that there is whitespace around the numbers in the OP's list, not just commas. Aug 8, 2022 at 8:58

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .