-2

RHEL 8, if it matters.

I need to find all the rows in a text file which match these three filters:

cut -f1 -d: .pgpass | grep ^FISP | grep -E 'CDS|TAP' | grep PGS401
FISPCDSPGS401A
FISPCDSPGS401B
FISPTAPPGS401AA
FISPTAPPGS401AB
FISPTAPPGS401BA
FISPTAPPGS401BB
FISPTAPPGS401CA
FISPTAPPGS401CB
FISPTAPPGS401DA
FISPTAPPGS401DB

This, similar to bash's extended globbing, is the kind of command I'm looking for, but doesn't match.

cut -f1 -d: .pgpass | grep '^FISP@(CDS|TAP)PGS401'
cut -f1 -d: .pgpass | grep -E '^FISP@(CDS|TAP)PGS401'

What's the secret sauce?

EDIT1: all the data

$ cut -f1 -d: .pgpass | grep -v '^$'
FISPCDSPGS202a
FISPCDSPGS202a
FISPCDSPGS202c
FISPCDSPGS202b
FISPCDSPGS202b
FISPCDSPGS202c
FISPCDSPGS202
FISPCCPGS302a
FISPCCPGS302b
FISPCCPGS302a
FISPCCPGS302b
FISPCCPGS302c
FISPCCPGS302
FISPCDSPGS302a
FISPCDSPGS302b
FISPCDSPGS302a
FISPCDSPGS302b
FISPCDSPGS302c
FISPCDSPGS302
FISPTAPPGS302a
FISPTAPPGS302b
FISPTAPPGS302a
FISPTAPPGS302b
FISPTAPPGS302c
FISPTAPPGS302
FISPCCPGS405a
FISPCCPGS405b
FISPCCPGS405a
FISPCCPGS405b
FISPCCPGS405c
FISPCCPGS405
FISPCDSPGS405a
FISPCDSPGS405b
FISPCDSPGS405a
FISPCDSPGS405b
FISPCDSPGS405c
FISPCDSPGS405
FISPTAPPGS405a
FISPTAPPGS405b
FISPTAPPGS405a
FISPTAPPGS405b
FISPTAPPGS405c
FISPTAPPGS405
FISPCDSPGS202c
FISPCCPGS302c
FISPCDSPGS302c
FISPTAPPGS302c
FISPCCPGS405c
FISPCDSPGS405c
FISPTAPPGS405c
FISSLBXPGS202a
FISSLBXPGS202b
FISSLBXPGS302a
FISSLBXPGS302b
FISSLBXPGS405a
FISSLBXPGS405b
FISPCDSPGS401A
FISPCDSPGS401B
FISPTAPPGS401AA
FISPTAPPGS401AB
FISPTAPPGS401BA
FISPTAPPGS401BB
FISPTAPPGS401CA
FISPTAPPGS401CB
FISPTAPPGS401DA
FISPTAPPGS401DB
FISQCCPGS401A
FISQCCPGS401B
FISQCCPGS401A
FISQCCPGS401B
FISQCCPGS401C
FISQCCPGS401
FISQCDSPGS401A
FISQCDSPGS401B
FISQCDSPGS401A
FISQCDSPGS401B
FISQCDSPGS401C
FISQCDSPGS401
FISQTAPPGS401A
FISQTAPPGS401B
FISQTAPPGS401A
FISQTAPPGS401B
FISQTAPPGS401C
FISQTAPPGS401

EDIT1: "dot and star" does not seem to work.

$ cut -f1 -d: .pgpass | grep '^FISP.*(CDS|TAP).*PGS401'
$ 

EDIT 2: How do you close a question, saying "needs details or clarity" when it has an accepted answer? That makes no sense.

5
  • 1
    Try removing the @ Commented Sep 12, 2024 at 16:44
  • @muru just tried. Didn't work. Commented Sep 12, 2024 at 16:47
  • It looks like you could simply fgrep for two strings FISPCDSPGS401 and FISPTAPPGS401 and no need to anchor this to the beginning of the line. Or do you also have more complicated cases? Commented Sep 12, 2024 at 17:05
  • @Bodo yeah, I could, but that seems inelegant. And yes, at some point in the Near Future the test will get more complicated. Commented Sep 12, 2024 at 17:09
  • 4
    What you posted as "all the data" has too many lines and too few columns. You don't need to post that many lines of sample input to demonstrate your problem and the right solution will work directly on your .pgpass file, not on the output of running cut on it. Also, showing sample input without the associated expected output isn't useful as we can't test a potential solution with that. Commented Sep 12, 2024 at 18:08

4 Answers 4

3

The command you can use is:

cut -f1 -d: .pgpass | grep -E '^FISP.*(CDS|TAP).*PGS401'

The will search for (regex) ^FISP.*CDS.*PGS401 or ^FISP.*TAP.*PGS401

Here is the result of execution, based on the OP input data:

#  grep -E '^FISP.*(CDS|TAP).*PGS401' vv
FISPCDSPGS401A
FISPCDSPGS401B
FISPTAPPGS401AA
FISPTAPPGS401AB
FISPTAPPGS401BA
FISPTAPPGS401BB
FISPTAPPGS401CA
FISPTAPPGS401CB
FISPTAPPGS401DA
FISPTAPPGS401DB
11
  • I added all the records to the Q, and also running your command. It did not work. Commented Sep 12, 2024 at 16:58
  • @RonJohn, I just run it with all data and will add the result in answer, please check because it work Commented Sep 12, 2024 at 16:59
  • 1
    I missed the -E. Commented Sep 12, 2024 at 17:03
  • 1
    @RonJohn, because it does not expect symbol(s) between PGS and 401 Commented Sep 12, 2024 at 17:08
  • 1
    @terdon if your grep doesn't support -E I can't imagine it'd support \| etc. as grep -E was around long before \| became supported by some grep versions in BREs. If your grep doesn't support -E it's time to get a newer version, e.g. one from the 1980s :-). Commented Sep 12, 2024 at 18:17
2

I'd try using \ to flip the "special" state* of your ()|s. You can do it like this:

grep '^FISP\(CDS\|TAP\)PGS401'
  • "special" state: prefacing a character with \ flips it from "just part of the string" to "special to the regular expression parser", or vice versa. Matching a literal ^ is \^.
1
  • 1
    Beware \| is a GNU extension. | is a standard operator in EREs, standard BREs have no equivalent, so portably, it's better to use grep -E '^FISP(CDS|TAP)PGS401' Commented Oct 26, 2024 at 9:32
1
cut -f1 -d: .pgpass | grep -E '^FISP@(CDS|TAP)PGS401'

You seem to have added an extra @ in that pattern, which doesn't match any of the input. Removing that fixes your problem:

printf '%s\n' \
    FISPCDSPGS401A \
    FISPCDSPGS401B \
    FISPTAPPGS401AA \
    FISPTAPPGS401AB \
    FISPTAPPGS401BA \
    FISPTAPPGS401BB \
    FISPTAPPGS401CA \
    FISPTAPPGS401CB \
    FISPTAPPGS401DA \
    FISPTAPPGS401DB |
  grep -E '^FISP(CDS|TAP)PGS401'
FISPCDSPGS401A
FISPCDSPGS401B
FISPTAPPGS401AA
FISPTAPPGS401AB
FISPTAPPGS401BA
FISPTAPPGS401BB
FISPTAPPGS401CA
FISPTAPPGS401CB
FISPTAPPGS401DA
FISPTAPPGS401DB
0

This may be what you're trying to do:

awk -F':' '{$0=$1} /^FISP/ && /CDS|TAP/ && /PG5401/' .pgpass

or maybe:

awk -F':' '{$0=$1} /^FISP.*(CDS|TAP).*PG5401/' .pgpass

without clear, testable sample input and expected output that's obviously an untested guess.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.