0

How can I skip printing on the line that matches pattern. For remaining lines display with the corresponding printf until a new line matches another pattern.

Want I want is the Wht:, Grn:, and Blu: codes to indicate the colour of subsequent text. So they're not to be output but instead used for changing the colour setting.

Here's what I have so far, which handles colouring but but doesn't do what I want:

theone ()
 {
  printf '%s\n' "$@"  \
    | while IFS="" read -r vl; do
       if [[ "$vl" =~ ^[[:space:]]*Wht:[[:space:]]*$ ]]; then
         printf '%s%s%s\n' "${wht}" "$vl" "${rst}"
       elif [[ "$vl" =~ ^[[:space:]]*Grn:[[:space:]]*$ ]]; then
         printf '%s%s%s\n' "${grn}" "$vl" "${rst}"
       elif [[ "$vl" =~ ^[[:space:]]*Blu:[[:space:]]*$ ]]; then
         printf '%s%s%s\n' "${blu}" "$vl" "${rst}"
       else
         printf '%s%s%s\n' "${wht}" "$vl" "${rst}"
       fi
      done
 }

Here is an example

var="
Grn:
  Some lines in green
  More green lites
  Green light again

Blu:
  Now turning to blue
  And more blue"

theone "$var"

The result would be

  Some lines in green
  More green lites
  Green light again

  Now turning to blue
  And more blue
Vera
  • 1,173
  • 4
  • 17
  • I'm trying to understand what you want. The code looks for `Wht:` (maybe surrounded by whitespace on either side) and if found prints it in what I assume is white text. Similarly green text for `Grn:` and blue for `Blu:`, with a fallback of white text for any other line. So what do you actually want instead of this? Please clarify this in your question - not here as a comment. An example might help (show input data and - as best you can - corresponding output) – roaima Feb 16 '23 at 23:01
  • I'm now wondering if you want the `Wht:`, `Grn:`, and `Blu:` to indicate the colour of subsequent text. So they're not to be output but instead used for changing the colour setting – roaima Feb 16 '23 at 23:04
  • You are correct on your last comment. Have called `continue` and `break`, but they would not continue to the next line. – Vera Feb 17 '23 at 09:03
  • 1
    Examples of input and expected output would be good to see. – Kusalananda Feb 17 '23 at 09:54
  • 1
    You should read [why-is-using-a-shell-loop-to-process-text-considered-bad-practice](https://unix.stackexchange.com/questions/169716/why-is-using-a-shell-loop-to-process-text-considered-bad-practice) to understand why you shouldn't be using a shell loop for this but instead should be using a text processing tool such as awk. – Ed Morton Feb 27 '23 at 17:36

1 Answers1

1

Here's one POSIX-compatible approach to the problem:

#!/bin/sh

# Colour codes
grn=$(tput setaf 2) blu=$(tput setaf 4) wht=$(tput setaf 7)
rst=$(tput sgr0)

theone()
{
    printf '%s\n' "$@" |
        while IFS= read -r vl
        do
            # Strip leading and trailing space
            ns=${vl##[[:space:]]}
            ns=${ns%%[[:space:]]}

            case "$ns" in
                # Look for a colour token
                Wht:)   use="$wht" ;;
                Grn:)   use="$grn" ;;
                Blu:)   use="$blu" ;;

                # Print a line
                *)      printf "%s%s%s\n" "${use:-$wht}" "$vl" "$rst" ;;
            esac
        done
}

If you're using bash you could alternatively put the colour codes into an associative array and look for entries in that instead of using a case … esac construct:

#!/bin/bash

theone()
{
    # Colour codes
    declare -A cc=(
        ['Grn:']=$(tput setaf 2)
        ['Blu:']=$(tput setaf 4)
        ['Wht:']=$(tput setaf 7)
    )
    local rst=$(tput sgr0)

    printf '%s\n' "$@" |
        while IFS= read -r vl
        do
            # Strip spaces
            ns=${vl//[[:space:]]/}

            # Look for a defined token
            if [[ -v cc[$ns] ]]
            then
                # Assign the next colour
                use=${cc[$ns]}
            else
                # Print a line
                printf "%s%s%s\n" "${use:-${cc['Wht:']}}" "$vl" "$rst"
            fi
        done
}
roaima
  • 107,089
  • 14
  • 139
  • 261