2

I have a file storing the course content taken by a student:

Sample outputA:

------------------------------------------------------------------------------------------------------------------------
                Year            Semester                Code             Credits                 Tag         letterGrade
------------------------------------------------------------------------------------------------------------------------
                2019              Autumn              CS 753                   6 Department elective                  AB
                2019              Autumn              CS 490                   6         Honors core                  CC
                2019              Autumn              CS 492                   6         Honors core                  FR
                2019              Autumn              CS 747                   6 Department elective                  FF
                2019              Autumn              ES 200                   3      Basic Sciences                  BC
                2019              Autumn              ET 601                   6  Institute Elective                  BB

I want to echo them to a terminal using a bash script with each line colored according to the course tag. The information on how to color is given in another file:

Source CSV to process ./resources/creditsRequirements.csv:

tag,credits,color_FONT,color_BACKGROUND,
Basic Sciences,62,CYAN,BLACK,
Engineering Science,29,BLACK,GREEN,
HSS Elective,12,GREEN,BLACK,
Institute Elective,12,BLACK,WHITE,
Core course,117,BLACK,CYAN,
Department elective,36,YELLOW,BLACK,
Honors core,24,WHITE,BLACK,
Minor,30,MAGENTA,WHITE,
Additional Learning,0,RED,WHITE,

I can't use any command other than sed or awk.

I want to do something like this (outputA and ./resources/creditRequirements.csv are command line arguments):

awk -F"," 'NR!=1{system("sed -e 's/^.\{1,\}($1).\{1,\}$/(code for color)&(code for reset)/g' "$1)}' $2

But this is happening (I used a shorter sed command just to test it):

./viewWithColor.sh outputA ./resources/creditsRequirements.csv
awk: cmd. line:1: NR!=1{system("sed -e /[0-9]/
awk: cmd. line:1:              ^ unterminated string
awk: cmd. line:1: NR!=1{system("sed -e /[0-9]/
awk: cmd. line:1:              ^ syntax error
Léa Gris
  • 17,497
  • 4
  • 32
  • 41
Rwitaban Goswami
  • 427
  • 3
  • 13

2 Answers2

1

You can do this with awk only:

colored.awk

#!/usr/bin/awk -f
function color_code(name) {
    switch(name) {
        case "BLACK":
            return 30
        case "RED":
            return 31
        case "GREEN":
            return 32
        case "YELLOW":
            return 33
        case "BLUE":
            return 34
        case "PURPLE":
            return 35
        case "CYAN":
            return 36
        case "WHITE":
            return 37
        default:
            return 37
    }   
}

function colored(str, fg_name, bg_name) {
    fg_code = color_code(fg_name)
    # The background color codes are the foreground color codes + 10
    bg_code = color_code(bg_name) + 10
    return "\033["fg_code";"bg_code"m"str"\033[0m"
}

# Read color assignments
NR==FNR {
    if (NR < 2) {
        next
    }   
    split($0,a,",")
    f[a[1]]=a[3]
    b[a[1]]=a[4]
    next
}

{
    for (i in f) {
        repl = colored(i, f[i], b[i])
        $0 = gensub(i, repl, 1)
    }   
    print
}

Make the file excutable and run it like this:

chmod +x colored.awk
./colored.awk resources/creditsRequirements.csv outputA
hek2mgl
  • 152,036
  • 28
  • 249
  • 266
1

This will do what you're trying to do in your posted awk{system(sed)) calls, you just need to populate it with a map of the color codes you want to use (see https://stackoverflow.com/a/28938235/1745001 for example).

$ cat tst.awk
BEGIN { FS = "," }
NR==FNR {
    if (FNR>1) {
        font[$1]  = $3
        back[$1]  = $4
        reset[$1] = "RESET"
    }
    next
}
{
    tag = $0
    sub(/^([[:space:]]+[^[:space:]]+){5}[[:space:]]+/,"",tag)
    sub(/[[:space:]]+[^[:space:]]+$/,"",tag)
    print back[tag] font[tag] $0 reset[tag]
}

$ awk -f tst.awk reqs.csv fileA
------------------------------------------------------------------------------------------------------------------------
                Year            Semester                Code             Credits                 Tag         letterGrade
------------------------------------------------------------------------------------------------------------------------
BLACKYELLOW                2019              Autumn              CS 753                   6 Department elective                  ABRESET
BLACKWHITE                2019              Autumn              CS 490                   6         Honors core                  CCRESET
BLACKWHITE                2019              Autumn              CS 492                   6         Honors core                  FRRESET
BLACKYELLOW                2019              Autumn              CS 747                   6 Department elective                  FFRESET
BLACKCYAN                2019              Autumn              ES 200                   3      Basic Sciences                  BCRESET
WHITEBLACK                2019              Autumn              ET 601                   6  Institute Elective                  BBRESET

e.g. something like this:

$ cat tst.awk
BEGIN {
    FS = ","

    map["RESET"] = "\033[0m"

    fg_map["BLACK"]  = "\033[0;30m"
    fg_map["RED"]    = "\033[0;31m"
    fg_map["GREEN"]  = "\033[0;32m"
    fg_map["YELLOW"] = "\033[0;33m"
    fg_map["BLUE"]   = "\033[0;34m"
    fg_map["PURPLE"] = "\033[0;35m"
    fg_map["CYAN"]   = "\033[0;36m"
    fg_map["WHITE"]  = "\033[0;37m"

    bg_map["BLACK"]  = "\033[0;40m"
    bg_map["RED"]    = "\033[0;41m"
    bg_map["GREEN"]  = "\033[0;42m"
    bg_map["YELLOW"] = "\033[0;43m"
    bg_map["BLUE"]   = "\033[0;44m"
    bg_map["PURPLE"] = "\033[0;45m"
    bg_map["CYAN"]   = "\033[0;46m"
    bg_map["WHITE"]  = "\033[0;47m"

}
NR==FNR {
    if (FNR>1) {
        font[$1]  = $3
        back[$1]  = $4
        reset[$1] = "RESET"
    }
    next
}
{
    tag = $0
    sub(/^([[:space:]]+[^[:space:]]+){5}[[:space:]]+/,"",tag)
    sub(/[[:space:]]+[^[:space:]]+$/,"",tag)
    print bg_map[back[tag]] fg_map[font[tag]] $0 map[reset[tag]]
}
Ed Morton
  • 188,023
  • 17
  • 78
  • 185