Let's create three test files:
echo 'xyz|abc' > c1
echo 'xyz|abc|wty' > c2
echo 'xyz|abc|wty|asd' > c3
gzip c*
Files containing one pipe in a line:
$ zgrep '^[^|]*|[^|]*$' *.gz
c1.gz:xyz|abc
For any other numbers (including one pipe in a line), you can use the following pattern:
Two pipes in a line:
$ zgrep -E '^([^|]*\|){2}[^|]*$' *.gz
c2.gz:xyz|abc|wty
Three pipes in a line:
$ zgrep -E '^([^|]*\|){3}[^|]*$' *.gz
c3.gz:xyz|abc|wty|asd
Two or three pipes in a line:
$ zgrep -E '^([^|]*\|){2,3}[^|]*$' *.gz
c2.gz:xyz|abc|wty
c3.gz:xyz|abc|wty|asd
Max. three pipes in a line:
$ zgrep -E '^([^|]*\|){,3}[^|]*$' *.gz
c1.gz:xyz|abc
c2.gz:xyz|abc|wty
c3.gz:xyz|abc|wty|asd
If you only need the filename, add option -l, i.e. zgrep -lE ...
My zgrep version doesn't support the recursive -r option.
You could use find for a recusive search and run zgrep on the result:
$ find . -type f -name '*.gz' -exec zgrep -lE '^([^|]*\|){3}[^|]*$' {} \;
./c3.gz