bashplural

How can I make a bash variable change a word between singular and plural endings based on a count of time?


I am not a good bash scripter yet.

In the following example script, I am trying to move through steps, check the amount of time elapsed since the step started, and use the correct singular or plural ending to describe the amount of time that has passed.

If the amount of time that passes rounds off to 1 second, I would like the script to tell me it took 1 "second" to move through the step and if it is anything else besides 1 second, I would like it to tell me it took x amount of "seconds"

#!\bin\bash
STEP=0
STEPS=4
RUN=1

while [ $RUN -eq 1 ]
do
    if (( RUNTIME == 1 ))
    then
      SEC="second"
    else
      SEC="seconds"
    fi


    STEP=$(( STEP + 1 ))
    printf "\\nStep $STEP/$STEPS\\n"
    printf "Hi!\\n"
    TIME=$SECONDS
    RUNTIME=$(( TIME - START_TIME ))
    printf "That took $RUNTIME $SEC\\n\\n"

    STEP=$(( STEP + 1 ))
    printf "Step $STEP/$STEPS\\n"
    printf "Hi!\\n"
    sleep 1s
    TIME1=$SECONDS
    RUNTIME=$(( TIME1 - TIME ))
    printf "That took $RUNTIME $SEC\\n\\n"

    STEP=$(( STEP + 1 ))
    printf "Step $STEP/$STEPS\\n"
    printf "Hi!\\n"
    sleep 2s
    TIME2=$SECONDS
    RUNTIME=$(( TIME2 - TIME1 ))
    printf "That took $RUNTIME $SEC\\n\\n"

    STEP=$(( STEP + 1 ))
    printf "Step $STEP/$STEPS\\n"
    printf "Hi!\\n"
    sleep 3s
    TIME3=$SECONDS
    RUNTIME=$(( TIME3 - TIME2 ))
    printf "That took $RUNTIME $SEC\\n\\n"

    END_TIME=$SECONDS
    RUNTIME=$(( END_TIME - START_TIME ))
    printf "The script took $RUNTIME $SEC to complete.\\n\\n"

    RUN=0

done

Solution

  • David, if you haven't found the issue yet, it's more o chicken-or-egg issue. Meaning you are setting SEC based on the value of RUNTIME at the beginning of the loop as opposed to the current value of RUNTIME immediately prior the output. A better way to handle this, rather than computing SEC at the top of the loop, is simply to write a small function that outputs either "second" or "seconds" based on the value of RUNTIME and incorporate that into your printf (which if you are not on WSL should not include double \\ within the format string -- though from your use of it, it looks like you are)

    You could do something simple like:

    #!/bin/bash
    
    STEP=0
    STEPS=4
    RUN=1
    
    secorsecs () {              ## simple sec or secs function based on $RUNTIME
        local seconds="second"  ## your base output is "second"
        if (( RUNTIME != 1 ))   ## if RUNTIME != 1
        then
            seconds+="s"        ## append an "s" to the end
        fi
        printf "%s" "$seconds"  ## output result
    }
    
    while [ $RUN -eq 1 ]
    do
        STEP=$(( STEP + 1 ))
        printf "\\nStep $STEP/$STEPS\\n"
        printf "Hi!\\n"
        TIME=$SECONDS
        RUNTIME=$(( TIME - START_TIME ))
        printf "That took $RUNTIME $(secorsecs)\\n\\n"
    
        STEP=$(( STEP + 1 ))
        printf "Step $STEP/$STEPS\\n"
        printf "Hi!\\n"
        sleep 1s
        TIME1=$SECONDS
        RUNTIME=$(( TIME1 - TIME ))
        printf "That took $RUNTIME $(secorsecs)\\n\\n"
    
        STEP=$(( STEP + 1 ))
        printf "Step $STEP/$STEPS\\n"
        printf "Hi!\\n"
        sleep 2s
        TIME2=$SECONDS
        RUNTIME=$(( TIME2 - TIME1 ))
        printf "That took $RUNTIME $(secorsecs)\\n\\n"
    
        STEP=$(( STEP + 1 ))
        printf "Step $STEP/$STEPS\\n"
        printf "Hi!\\n"
        sleep 3s
        TIME3=$SECONDS
        RUNTIME=$(( TIME3 - TIME2 ))
        printf "That took $RUNTIME $(secorsecs)\\n\\n"
    
        END_TIME=$SECONDS
        RUNTIME=$(( END_TIME - START_TIME ))
        printf "The script took $RUNTIME $(secorsecs) to complete.\\n\\n"
    
        RUN=0
    
    done
    

    Example Use/Output

    $ bash seconds.sh
    
    Step 1/4
    Hi!
    That took 0 seconds
    
    Step 2/4
    Hi!
    That took 1 second
    
    Step 3/4
    Hi!
    That took 2 seconds
    
    Step 4/4
    Hi!
    That took 3 seconds
    
    The script took 6 seconds to complete.
    

    Look things over and let me know if you have further questions.