Skip to main content
[Edit removed during grace period]
Source Link
Remove deprecated note
Source Link
  • The -E option enables extended expression syntax (ERE) for grep.

  • The -i option tells grep to match case-insensitive

  • The -v option tells grep to invert the result (i.e. match lines not containing the pattern)

  • The -c option tells grep to output the number of matched lines instead of the lines themselves

  • The patterns:

    1. \< matches the beginning of a word (thanks @glenn-jackman@glenn-jackman)
    2. \> matches the end of a word (thanks @glenn-jackman@glenn-jackman)

    --> That way we can make sure to not match words containing 'the' or 'an' (like 'pan')

    1. grep -Evi -e '\<an\>.*\<the\>' thus matches all lines not containing 'an ... the' ~(Note: I did purposefully not include the case "an the" ('the' directly following on 'an' because it is an unlikely case and I wanted to keep the pattern simple. It could, of course, easily be added)~.

      grep -Evi -e '\<an\>.*\<the\>' thus matches all lines not containing 'an ... the'

    2. Similarly, grep -Evi -e '\<the\>.*\<an\>' matches all lines not containing 'the ... an'

      Similarly, grep -Evi -e '\<the\>.*\<an\>' matches all lines not containing 'the ... an'

    3. grep -Evi -e '\<an\>.*\<the\>' -e '\<the.*an\>' is the combination of the 3. and 4.

      grep -Evi -e '\<an\>.*\<the\>' -e '\<the.*an\>' is the combination of the 3. and 4.

    4. grep -Eci -e '\<(an|the)\>' matches all lines containing either 'an' or 'the' (surrounded by whitespace or start/end of line) and prints the number of matched lines

      grep -Eci -e '\<(an|the)\>' matches all lines containing either 'an' or 'the' (surrounded by whitespace or start/end of line) and prints the number of matched lines

  • The -E option enables extended expression syntax (ERE) for grep.

  • The -i option tells grep to match case-insensitive

  • The -v option tells grep to invert the result (i.e. match lines not containing the pattern)

  • The -c option tells grep to output the number of matched lines instead of the lines themselves

  • The patterns:

    1. \< matches the beginning of a word (thanks @glenn-jackman)
    2. \> matches the end of a word (thanks @glenn-jackman)

    --> That way we can make sure to not match words containing 'the' or 'an' (like 'pan')

    1. grep -Evi -e '\<an\>.*\<the\>' thus matches all lines not containing 'an ... the' ~(Note: I did purposefully not include the case "an the" ('the' directly following on 'an' because it is an unlikely case and I wanted to keep the pattern simple. It could, of course, easily be added)~.
    2. Similarly, grep -Evi -e '\<the\>.*\<an\>' matches all lines not containing 'the ... an'
    3. grep -Evi -e '\<an\>.*\<the\>' -e '\<the.*an\>' is the combination of the 3. and 4.
    4. grep -Eci -e '\<(an|the)\>' matches all lines containing either 'an' or 'the' (surrounded by whitespace or start/end of line) and prints the number of matched lines
  • The -E option enables extended expression syntax (ERE) for grep.

  • The -i option tells grep to match case-insensitive

  • The -v option tells grep to invert the result (i.e. match lines not containing the pattern)

  • The -c option tells grep to output the number of matched lines instead of the lines themselves

  • The patterns:

    1. \< matches the beginning of a word (thanks @glenn-jackman)
    2. \> matches the end of a word (thanks @glenn-jackman)

    --> That way we can make sure to not match words containing 'the' or 'an' (like 'pan')

    1. grep -Evi -e '\<an\>.*\<the\>' thus matches all lines not containing 'an ... the'

    2. Similarly, grep -Evi -e '\<the\>.*\<an\>' matches all lines not containing 'the ... an'

    3. grep -Evi -e '\<an\>.*\<the\>' -e '\<the.*an\>' is the combination of the 3. and 4.

    4. grep -Eci -e '\<(an|the)\>' matches all lines containing either 'an' or 'the' (surrounded by whitespace or start/end of line) and prints the number of matched lines

Add notice for alternative syntax
Source Link

With grep:

cat poem.txt \
  | grep -Evi -e '\<an\>.*\<the\>' -e '\<the\>.*\<an\>' \
  | grep -Eci -e '\<(an|the)\>'

This counts the matched lines. You can find an alternative syntax which counts the total number of matches down below.

Breakdown:

The frist grep command filters out all lines containing both 'an' and 'the'. The second grep command counts those lines, containing either 'an' or 'the'.

If you remove the c from the second grep's -Eci, you will see all matches highlighted.

Details:

  • The -E option enables extended expression syntax (ERE) for grep.

  • The -i option tells grep to match case-insensitive

  • The -v option tells grep to invert the result (i.e. match lines not containing the pattern)

  • The -c option tells grep to output the number of matched lines instead of the lines themselves

  • The patterns:

    1. \< matches the beginning of a word (thanks @glenn-jackman)
    2. \> matches the end of a word (thanks @glenn-jackman)

    --> That way we can make sure to not match words containing 'the' or 'an' (like 'pan')

    1. grep -Evi -e '\<an\>.*\<the\>' thus matches all lines not containing 'an ... the' ~(Note: I did purposefully not include the case "an the" ('the' directly following on 'an' because it is an unlikely case and I wanted to keep the pattern simple. It could, of course, easily be added)~.
    2. Similarly, grep -Evi -e '\<the\>.*\<an\>' matches all lines not containing 'the ... an'
    3. grep -Evi -e '\<an\>.*\<the\>' -e '\<the.*an\>' is the combination of the 3. and 4.
    4. grep -Eci -e '\<(an|the)\>' matches all lines containing either 'an' or 'the' (surrounded by whitespace or start/end of line) and prints the number of matched lines

EDIT 1: Use \< and \> instead of ( |^) and ( |$), as suggested by @glenn-jackman

EDIT 2: In order to count the number of matches instead of the number of matched lines, use the following expression:

cat poem.txt \
  | grep -Evi -e '\<an\>.*\<the\>' -e '\<the\>.*\<an\>' \
  | grep -Eio -e '\<(an|the)\>' \
  | wc -l

This uses the -o option of grep, which prints every match in a separate line (and nothing else) and then wc -l to count the lines.

With grep:

cat poem.txt \
  | grep -Evi -e '\<an\>.*\<the\>' -e '\<the\>.*\<an\>' \
  | grep -Eci -e '\<(an|the)\>'

Breakdown:

The frist grep command filters out all lines containing both 'an' and 'the'. The second grep command counts those lines, containing either 'an' or 'the'.

If you remove the c from the second grep's -Eci, you will see all matches highlighted.

Details:

  • The -E option enables extended expression syntax (ERE) for grep.

  • The -i option tells grep to match case-insensitive

  • The -v option tells grep to invert the result (i.e. match lines not containing the pattern)

  • The -c option tells grep to output the number of matched lines instead of the lines themselves

  • The patterns:

    1. \< matches the beginning of a word (thanks @glenn-jackman)
    2. \> matches the end of a word (thanks @glenn-jackman)

    --> That way we can make sure to not match words containing 'the' or 'an' (like 'pan')

    1. grep -Evi -e '\<an\>.*\<the\>' thus matches all lines not containing 'an ... the' ~(Note: I did purposefully not include the case "an the" ('the' directly following on 'an' because it is an unlikely case and I wanted to keep the pattern simple. It could, of course, easily be added)~.
    2. Similarly, grep -Evi -e '\<the\>.*\<an\>' matches all lines not containing 'the ... an'
    3. grep -Evi -e '\<an\>.*\<the\>' -e '\<the.*an\>' is the combination of the 3. and 4.
    4. grep -Eci -e '\<(an|the)\>' matches all lines containing either 'an' or 'the' (surrounded by whitespace or start/end of line) and prints the number of matched lines

EDIT 1: Use \< and \> instead of ( |^) and ( |$), as suggested by @glenn-jackman

EDIT 2: In order to count the number of matches instead of the number of matched lines, use the following expression:

cat poem.txt \
  | grep -Evi -e '\<an\>.*\<the\>' -e '\<the\>.*\<an\>' \
  | grep -Eio -e '\<(an|the)\>' \
  | wc -l

With grep:

cat poem.txt \
  | grep -Evi -e '\<an\>.*\<the\>' -e '\<the\>.*\<an\>' \
  | grep -Eci -e '\<(an|the)\>'

This counts the matched lines. You can find an alternative syntax which counts the total number of matches down below.

Breakdown:

The frist grep command filters out all lines containing both 'an' and 'the'. The second grep command counts those lines, containing either 'an' or 'the'.

If you remove the c from the second grep's -Eci, you will see all matches highlighted.

Details:

  • The -E option enables extended expression syntax (ERE) for grep.

  • The -i option tells grep to match case-insensitive

  • The -v option tells grep to invert the result (i.e. match lines not containing the pattern)

  • The -c option tells grep to output the number of matched lines instead of the lines themselves

  • The patterns:

    1. \< matches the beginning of a word (thanks @glenn-jackman)
    2. \> matches the end of a word (thanks @glenn-jackman)

    --> That way we can make sure to not match words containing 'the' or 'an' (like 'pan')

    1. grep -Evi -e '\<an\>.*\<the\>' thus matches all lines not containing 'an ... the' ~(Note: I did purposefully not include the case "an the" ('the' directly following on 'an' because it is an unlikely case and I wanted to keep the pattern simple. It could, of course, easily be added)~.
    2. Similarly, grep -Evi -e '\<the\>.*\<an\>' matches all lines not containing 'the ... an'
    3. grep -Evi -e '\<an\>.*\<the\>' -e '\<the.*an\>' is the combination of the 3. and 4.
    4. grep -Eci -e '\<(an|the)\>' matches all lines containing either 'an' or 'the' (surrounded by whitespace or start/end of line) and prints the number of matched lines

EDIT 1: Use \< and \> instead of ( |^) and ( |$), as suggested by @glenn-jackman

EDIT 2: In order to count the number of matches instead of the number of matched lines, use the following expression:

cat poem.txt \
  | grep -Evi -e '\<an\>.*\<the\>' -e '\<the\>.*\<an\>' \
  | grep -Eio -e '\<(an|the)\>' \
  | wc -l

This uses the -o option of grep, which prints every match in a separate line (and nothing else) and then wc -l to count the lines.

Add solution to the current version of the question
Source Link
Loading
added 94 characters in body
Source Link
Loading
added 1 character in body
Source Link
Loading
Source Link
Loading