Search code examples
bashsetw

Setw and setfill equivalent in BASH


Could you please tell me what the equivalent BASH code for the following C++ snippet would be:

std::cout << std::setfill('x') << std::setw(7) << 250;

The output is:

xxxx250

Thanks for the help!


Solution

  • If you're on Linux, it has a printf program for just this purpose. Other UNIX variants may also have it.

    Padding a numeric with x is not really on of its use cases but you could get the same result with:

    pax> printf "%7d\n" 250 | tr ' ' 'x'
    xxxx250
    

    That outputs the 250 with space padding, then uses the tr translate utility to turn those spaces into x characters.

    If you're looking for a bash-only solution, you can start with:

    pax> n=250 ; echo ${n}
    250
    
    pax> n=xxxxxxx${n} ; echo ${n}
    xxxxxxx250
    
    pax> n=${n: -7} ; echo ${n}
    xxxx250
    

    If you want a generalised solution, you can use this function fmt, unit test code is included:

    #!/bin/bash
    #
    # fmt <string> <direction> <fillchar> <size>
    # Formats a string by padding it to a specific size.
    # <string> is the string you want formatted.
    # <direction> is where you want the padding (l/L is left,
    #    r/R and everything else is right).
    # <fillchar> is the character or string to fill with.
    # <size> is the desired size.
    #
    fmt()
    {
        string="$1"
        direction=$2
        fillchar="$3"
        size=$4
        if [[ "${direction}" == "l" || "${direction}" == "L" ]] ; then
            while [[ ${#string} -lt ${size} ]] ; do
                string="${fillchar}${string}"
            done
            string="${string: -${size}}"
        else
            while [[ ${#string} -lt ${size} ]] ; do
                string="${string}${fillchar}"
            done
            string="${string:0:${size}}"
        fi
        echo "${string}"
    }
    

     

    # Unit test code.
    
    echo "[$(fmt 'Hello there' r ' ' 20)]"
    echo "[$(fmt 'Hello there' r ' ' 5)]"
    echo "[$(fmt 'Hello there' l ' ' 20)]"
    echo "[$(fmt 'Hello there' l ' ' 5)]"
    echo "[$(fmt 'Hello there' r '_' 20)]"
    echo "[$(fmt 'Hello there' r ' .' 20)]"
    echo "[$(fmt 250 l 'x' 7)]"
    

    This outputs:

    [Hello there         ]
    [Hello]
    [         Hello there]
    [there]
    [Hello there_________]
    [Hello there . . . . ]
    [xxxx250]
    

    and you're not limited to just printing them, you can also save the variables for later with a line such as:

    formattedString="$(fmt 'Hello there' r ' ' 20)"