10

I wrote a little Bash script, that uses spfquery for checking upon my domain email SPF record, if it passes on all providers IP addresses:

#!/bin/bash

# RED="\033[1;31m"
GREEN="\033[1;32m"
NOCOLOR="\033[0m"

email="[my email address]" # deleted for bots not to hound me

declare -a ips=("88.86.120.212" "88.86.120.223" "88.86.120.250" "88.86.120.213" "88.86.120.103" "46.234.104.23" "46.234.104.24")

echo -e "\n\n"

for ip in "${ips[@]}"
do
    echo -e "${GREEN}$ip${NOCOLOR}"
    spfquery -sender $email -ip $ip -helo kolbaba.stable.cz
    echo -e "\n\n"
done

Notice, there is RED commented out. That's because I would like the resulting message starting with any of these:

  • fail
  • softfail
  • neutral
  • unknown
  • error
  • none

i.e. not with:

  • pass

to colorize in red.

But how to do this is a mystery to me?

1

3 Answers 3

24

With zsh instead of bash:

#! /bin/zsh -

email="[email protected]"

ips=(88.86.120.{212,223,250,213,103} 46.234.104.{23,24})

print '\n\n'

for ip ($ips) {
  spfquery -sender $email -ip $ip -helo kolbaba.stable.cz &&
    color=green || color=red

  print -P "%F{$color}$ip%f\n"
}

print -P turns on prompt expansion on the arguments where %F{color} is to set the foreground colour, and %f to reset it.

Note that the content of the variables in there ($color and $ip) are also subject to prompt expansion (something to bear in mind in cases where they may contain % characters (or more if the promptsubst option is enabled)), and without -r, escape sequence expansion (like \n above).

Other ways to access colours in zsh:

  • the colors autoloadable function:

    autoload colors; colors
    echo $fg[green]text$reset_color
    
  • the % parameter expansion flag, that enables prompt expansion on the content of a variable:

    var='%F{green}' reset=%f
    echo ${(%)var}text${(%)reset}
    

    see also:

    echo ${(%):-%F{green\}}text${(%):-%f}
    

    or better

    printf '%s\n' "${(%):-%F{green\}}$text${(%):-%f}"
    

    to guarantee the content of $text is output as-is and not also subject to prompt expansion.

    Assuming the promptpercent option is enabled and promptbang and promptsubst options are disabled as they are by default, you can also replace all %s with %%s in $text before passing to print -rP:

    print -rP -- "%F{green\}}$text:gs/%/%%/%f"
    

    (or use the ${text//\%/%%} equivalent from the Korn shell instead of the csh-style $text:gs/x/y/)

  • the zsh/curses module used to write pseudo-graphical applications in the terminal.

5
  • ${(%)reset} seems like % used double times because reset=%f where % is used?
    – Timo
    Commented Jun 17, 2021 at 7:03
  • I use zsh 5.8 and do not get colored output with none of your code in a script. On terminal, it works but echo ${(%):-green}text${(%):-%f} and printf '%s\n' "${(%):-green}$text${(%):-%f}" does not print green output in termninal.
    – Timo
    Commented Jun 17, 2021 at 7:55
  • @Timo, and what does echoti colors output? Commented Jun 17, 2021 at 8:48
  • Regarding echoti colors I get 256 in the terminal.
    – Timo
    Commented Jun 17, 2021 at 14:04
  • @Timo, sorry my bad. Typo, code did not include the prompt escape! Commented Jun 17, 2021 at 14:59
9

You would want to check the exit code of spfquery, then have an if/else to see if it was a pass or not. Something like this:

#!/bin/bash

RED="\033[1;31m"
GREEN="\033[1;32m"
NOCOLOR="\033[0m"

email="[email protected]"

declare -a ips=("88.86.120.212" "88.86.120.223" "88.86.120.250" "88.86.120.213" "88.86.120.103" "46.234.104.23" "46.234.104.24")

echo -e "\n\n"

for ip in "${ips[@]}"
do
    spfquery -sender $email -ip $ip -helo kolbaba.stable.cz

    exit_status=$?
    if [ $exit_status -eq 0 ]; then
        echo -e "${GREEN}$ip${NOCOLOR}"
    else
        echo -e "${RED}$ip${NOCOLOR}"
    fi

    echo -e "\n\n"
done
3
  • I'm not sure. Per the documentation you linked for spfquery, a pass returns exit code 0, and each other return type returns a non-zero code (what we're checking for in the if statement).
    – Jason Rush
    Commented Dec 5, 2017 at 6:15
  • I will contact the developer and report it as a bug. Because it returns pass, while return code is 2. Thank you for the answer. Commented Dec 5, 2017 at 6:20
  • Explicitly comparing $? to zero is a widespread antipattern. Anything which looks like cmd; if [ $? -eq 0 ]; then is better written if cmd; then. The very purpose of the shell's flow control statements is to run a command sequence and check its exit status to decide a conditional.
    – tripleee
    Commented Aug 15, 2018 at 6:35
4

I would like the resulting message starting with any of these […] to colorize in red.

Your question reads that you would like to colour the output generated by the spfquery command. This is not achieved by running the command and then emitting colour change control sequences. What you are achieving with the other answers is colouring just the IP addresses. This may be what you want, but it is not what your question asks for.

The tools that you are looking for if this is what you really want to do are the various colourization filter utilities, such as István Karaszi's colorize, Radovan Garabík's grc, and Joakim Andersson's colortail. Configure them to recognize the appropriate things, and then pipe the output of spfquery, or indeed the entire for loop, through them.

Further reading

2

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .