Como exportar colunas usando Bash built-in 'printf' onde a fonte contém cores?

3

O código é:

#!/bin/bash
ips[0]='192.168.0.1'
ips[1]='192.168.0'
ips[2]='255.255.255.256'
ips[3]='123.123.123.123.123'
ips[4]='a.b.c.d'
ips[5]='255.255.255.255'
ips[6]='0.0.0.0'
ips[7]='192.168.1.1'
ips[8]='4.2.2.2'

regex="^((25[0-5]|2[0-4][0-9]|[01][0-9][0-9]|[0-9]{1,2})[.]){3}(25[0-5]|2[0-4][0-9]|[01][0-9][0-9]|[0-9]{1,2})$"

regexVar=$(printf "3[33mSaved in a VARIABLE3[0m")
regexStr=$(printf "3[34mIs a STRING3[0m")
validOut=$(printf "3[32mValid3[0m")
invalidOut=$(printf "3[31mInvalid3[0m")
noQuotes="NO quotes"
singleQuotes="Single quotes"
doubleQuotes="Double quotes"

printStyle="%-25s %-10s %-20s %-10s\n"
printTitle=$(printf "${printStyle}" "IP Address" "Validity" "Regex" "Quote Type")
print2ndLine=$(printf "${printStyle}" "====================" "==========" "====================" "==========")

function validIP1a() {
    echo "${printTitle}"
    echo "${print2ndLine}"
    for (( i=0; i<${#ips[@]}; i++ )); do
        if [[ "${ips[i]}" =~ $regex ]]; then
            printf "${printStyle}" "${ips[i]}" "${validOut}" "${regexVar}" "${noQuotes}"
        else
            printf "${printStyle}" "${ips[i]}" "${invalidOut}" "${regexVar}" "${noQuotes}"
        fi
    done
}

validIP1a

A saída é:

Asaídaesperadaé:

Por que não consigo obter o resultado esperado? Como resolver isso?

    
por liyang 25.11.2017 / 14:22

2 respostas

3

Porque printf conta os caracteres no código de escape que define a cor; não sabe que não imprimem realmente. Você precisaria colocá-los fora das cadeias formatadas com comprimento fixo ( %-20s ). Compare os dois printf s aqui:

#!/bin/bash
green=$'3[32m'
yellow=$'3[33m'
normal=$'3[0m'

printf "1234567890123456789012345678901234567\n";
printf "%-20s %s\n" "${yellow}some string${normal}"  "next col"
printf "${yellow}%-20s${normal} %s\n" "some string"  "next col"

A saída deve ficar assim:

Claro,seacormudar,podemoscolocá-laemoutravariável:

printf"%s%-20s${normal} %s\n" "$green" "some string"  "next col"
    
por 25.11.2017 / 14:34
2

Você pode querer contar os caracteres em validOut e invalidOut ; Eu conto mais de 10 em cada um deles:

#                                11   11111
#                    1   2245678901   23456
  validOut=$(printf "3[32mValid3[0m")
invalidOut=$(printf "3[31mInvalid3[0m")

Lembre-se que printf ruim não pode saber que alguns desses caracteres são invisíveis e fazem alterações de cor ... Você solicitou um campo alinhado à esquerda de pelo menos 10 caracteres e, em seguida, preencheu com strings com mais de 10 caracteres; não admira que o resultado não esteja alinhado verticalmente.

    
por 25.11.2017 / 14:32