0

I'm trying to write a small bash script that will check if each element of a sequence of numbers is in a given file, and print the ones that aren't.

find_missing.sh:

#!/bin/bash
for num in {1..5}; do
    if ! [[ $(grep -q "$num" numbers.txt) ]]; then
        echo "$num"
    fi
done

numbers.txt:

1
2
5

Expected output:

3
4

Actual output:

1
2
3
4
5

If I change the line grep -q "$num" numbers.txt to grep "$num" numbers.txt, I get the expected output. However, my understanding is that the -q flag should be returning an exit code of 0 if the number is found and an exit code of 1 if it isn't found, and I don't understand why having or not having the flag makes a difference.

If I try to run individual instances of the grep command, I get the behavior I expect:

grep -q "1" numbers.txt; echo "$?"
0
grep -q "3" numbers.txt; echo "$?"
1

Can anyone help me understand what's going on here?

1
  • $( ... ) captures the output, but grep -q produces no output.
    – choroba
    Commented Jul 27, 2021 at 15:34

1 Answer 1

2

$( ... ) captures the output, but grep -q produces no output. Don't use it. You don't even need the square brackets as if can use the exit status:

if ! grep -q "$num" numbers.txt ; then

You can get the same output with

printf '%s\n' {1..5} | grep -vwFf numbers.txt -
2
  • What exactly is the final - signifying in your alternate construction? Commented Jul 27, 2021 at 15:52
  • 1
    @NathanPierson The - tells grep to search its standard input (in this case, the input from the pipe). See #13 in the POSIX utility syntax guidelines. Note that the numbers.txt file is not what's being searched, it's an argument to the -f option, meaning that its contents will be used as a list of things to search for (or rather, search for the absence of, because the -v option inverts the search). Commented Jul 27, 2021 at 21:52

You must log in to answer this question.

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