MB-20
MB-20

Reputation: 53

How can I use GREP to decide if every line in a file matches my pattern?

I am trying to check if every line in a file matches my pattern (4 characters followed by 4 digits). I tried using GREP with -x -P -v -q options so it returns 1 if my file doesn't match the requirements. I expect it to return nothing in case the file is correct, but it returns nothing even if the file has an error. $4 is my input file. My code is:

if [ -f $4 ] && [ `grep -q -P -x -v [[a-z]x{4}/[\dx{4}] $4` ]
then
echo "error"
exit 1
fi

input example: bmkj2132 ahgc3478 (no uppercase)

Upvotes: 5

Views: 1240

Answers (3)

choroba
choroba

Reputation: 242403

Don't check the output of grep, check its exit code.

if [ -f "$4" ] && grep -q ...

Note the double quotes around $4 - otherwise a file name containing whitespace will break the script.

Also, single quote the regex. Square brackets are special in bash and you don't want the regex to suddenly change (expand) when a random filename exists.

Also note that x doesn't mean "times" (under -e, -E, -P neither). The quantifier just follows the quantified with no operator in between:

echo abcd1234 | grep -xP '[a-z]{4}\d{4}'

So, the full condition should be

if [ -f "$4" ] && grep -qvxP '[a-z]{4}\d{4}' "$4" ; then
    echo Error >&2
    exit 1
fi

Are you sure you want to continue if the file doesn't exist? If not, change the condition to

if ! [ -f "$4" ] || grep ...

BTW, you don't really need the PCRE expression here. If you replace \d by [0-9] or [[:digit:]], you can switch to -E (extended regular expression).

Upvotes: 6

CosmicCamel
CosmicCamel

Reputation: 46

This answer describes how we can use grep to search for any line not matching a particular regex pattern. We can modify this to provide a one-liner.

grep -Evq "[1-2]" file.txt && echo "error" && exit 1 || true

On the following file.txt, the error message and exit code will be triggered:

1
2
3

Without || true, this will always have an false return code. Additionally, this only works for the specified use case; modifying exit 1 to something like true will break the one-liner.

The regex pattern included within this example should be modified to the desired pattern.

Upvotes: 1

Ljm Dullaart
Ljm Dullaart

Reputation: 4989

The point about using the exit code of grep is that it does not match the required condition.

Try the following:

if [ -f "$4" ] ; then
    wronglines=$(grep -v pattern "$4")
    if [ "$wronglines" = "" ] ; then
        echo "all is well"
    else
        echo "a wrong line in the file"
    fi
else
    echo "cannot even find the file"
fi

Upvotes: 1

Related Questions