Search code examples
bashcolorsgrep

grep: color different parts of output


I'm trying to output some text from grep and highlight in different colors. This is my data:

    - name: the name
      displayName: "[JIRA REF] the name"
      description: JIRA REF
      exemptionCategory: waiver
      expiresOn: 2024-03-02T00:00:00Z
      policyDefinitionReferenceIds:
        - REFid
      scope: null

I need each key (name, displayName etc) in blue and JIRA REF in red

I've managed to isolate it so the key is one color, but when I add in a secondary condition it only matches that eg

grep -A3 -B4 -P 2024-03-02 --color=auto file.txt \
| grep --color=auto -P \
'expiresOn|displayName|name|exemptionCategory|policyDefinitionReferenceIds|scope|description' \ 
-A3 -B4

will output each key in red, but when I add in

grep -A3 -B4 -P 2024-03-02 --color=auto file.txt \
| grep --color=auto -P \
'expiresOn|displayName|name|exemptionCategory|policyDefinitionReferenceIds|scope|description' \ 
-A3 -B4 \
| GREP_COLOR='mt=01;31' grep --color=auto -P '.{0,0}JIRA.{0,4}' \
-A3 -B4

only the JIRA REF is colored


Solution

  • An unoptimized "least effort" solution

    While there are better solutions elsewhere on this page, this post (going with my comment to provide actual code) focuses on your current approach (using multiple greps, sequentially piped into one another) to highlight what went wrong, and how to fix it for a "least effort" solution.

    GREP_COLORS='mt=01;35' grep --color=always -A3 -B4 -P '2024-03-02' file.txt |
    GREP_COLORS='mt=01;34' grep --color=always -A3 -B4 -P 'expiresOn|displayName|name|exemptionCategory|policyDefinitionReferenceIds|scope|description' |
    GREP_COLORS='mt=01;31' grep --color=always -A3 -B4 -P '.{0,0}JIRA.{0,4}'
    #         ^        ^^               ^^^^^^
    #     spelling    color         coloring mode
    

    Apart from some uniform formatting to improve readability, the following changes were applied:

    • GREP_COLORS is spelled with an S at the end
    • Setting different colors for each line, including 34 for blue, and leaving 31 for red
    • Changing --color=auto to --color=always as with auto, coloring is only enabled for printing, but disabled when piping into another process. (Thus, the last grep doesn't actually need to be modified for this use-case, but I included it anyway for consistency and potentially needed interoperability.)