Home > Enterprise >  bash - Conditional for filtering on string '15m' or less
bash - Conditional for filtering on string '15m' or less

Time:09-23

I'm checking the age of an object, and it gives me one of the following types of outputs, e.g: 30s, 15m, 3h, 17d. (meaning 30 seconds, 15 minutes, 3 hours, 17 days, respectfully)

Each of these is just a simple string.

What's the best way to say: "if under 15m, continue, else break"?

I can only think of

if 's' or 'm' not in 'string' then break

if 'm' in 'string' and '2-digits-preceding-m' > 15 then break

Is there a more elegant way of doing this, possibly in which I can turn these values into actual timestamps to compare more robustly?

CodePudding user response:

Case statements are easy to read and maintain.

for num in 5 20; do       
  for unit in s m h d; do
    case "$unit" in
    s) echo "seconds ok: $n$u"                                       ;;
    m) if (( num < 15)) then; echo "Min $num < 15 ok: $num$unit" 
       else                   echo "Min 15 , break: $num$unit"       ;;
    *) echo "Time > minutes, break: $num$unit"                       ;;
    esac
  done
done

output:

seconds ok: 5s
Min 5 < 15 ok: 5m
Time > minutes, break: 5h
Time > minutes, break: 5d
seconds ok: 20s
Min 15 , break: 20m
Time > minutes, break: 20h
Time > minutes, break: 20d

A simple if structure works too.

for num in 5 20; do
  for unit in s m h d; do
    if   [[ s == "$unit" ]]                   ; then echo "seconds ok: $num$unit";     
    elif [[ m == "$unit" ]] && (( num < 15 )) ; then echo "Min $num < 15 ok: $num$unit";
    else                                             echo "Time > 15m: $num$unit";     
    fi
  done
done

output:

seconds ok: 5s
Min 5 < 15 ok: 5m
Time > 15m: 5h
Time > 15m: 5d
seconds ok: 20s
Time > 15m: 20m
Time > 15m: 20h
Time > 15m: 20d

I think unless a regex is pretty complicated you're going to have to break it out into multiple tests anyway, so why not keep it simple?

CodePudding user response:

#! /bin/bash

makeHorodate () {
    # Initialize counters
    local -i SECONDS=0
    local -i MINUTES=0
    local -i HOURS=0
    local -i DAYS=0
    # Loop on elements
    for ELT in $1; do
        # Remove comas
        ELT=${ELT//,/}
        # Check element format
        [[ ! "${ELT}" =~ ^[0-9] [smhd]$ ]] && echo "oops. element '${ELT}' not recognized" >&2 && return 1
        # Remove '0'
        while [[ "${ELT:0:1}" == 0 ]]; do ELT=${ELT:1}; done
        [[ "${ELT}" =~ ^[smhd]$ ]] && ELT="0${ELT}"
        # Add values in good counter
        case "${ELT}" in
            *s)
                SECONDS =${ELT%s}
            ;;
            *m)
                MINUTES =${ELT%m}
            ;;
            *h)
                HOURS =${ELT%h}
            ;;
            *d)
                DAYS =${ELT%d}
            ;;
        esac
    done
    # Format output in a big number
    local RESULT=0
    printf -v RESULT "%dddd" ${DAYS} ${HOURS} ${MINUTES} ${SECONDS}
    while [[ "${RESULT:0:1}" == 0 ]]; do RESULT=${RESULT:1}; done
    [[ "${RESULT}" == "" ]] && RESULT=0
    echo -n "${RESULT}"
    return 0
}

echo $(makeHorodate "30s, 15m, 3h, 17d")
echo $(makeHorodate "44s, 23m, 17h, 5d")
# with '0'
echo $(makeHorodate "03s, 002m, 01h, 0d")
# different elements order -> same result
echo $(makeHorodate "01h, 002m, 03s, 0d")
# some values
echo $(makeHorodate "3m, 15d")
# just 15 seconds
echo $(makeHorodate "15s")

# now numeric comparisons are possible between any values
if [[ $(makeHorodate "01h, 002m, 03s, 0d") -eq $(makeHorodate "03s, 002m, 01h, 0d") ]]; then
    echo "Equal"
fi
# Test > 15 seconds
if [[ $(makeHorodate "01h, 002m, 03s, 0d") -gt $(makeHorodate "15s") ]]; then
    echo "> 15 seconds"
fi
# Other test for 15 seconds
if [[ $(makeHorodate "01h, 002m, 03s, 0d") -gt 15 ]]; then
    echo "> 15 seconds"
fi
# Test > 3 minutes
if [[ $(makeHorodate "01h, 002m, 03s, 0d") -gt $(makeHorodate "3m") ]]; then
    echo "> 3 minutes"
fi
# Other test > 3 minutes
if [[ $(makeHorodate "01h, 002m, 03s, 0d") -gt 3000 ]]; then
    echo "> 3 minutes"
fi

Output:

17003015030
5017023044
1002003
1002003
15000003000
15
Equal
> 15 seconds
> 15 seconds
> 3 minutes
> 3 minutes
  •  Tags:  
  • bash
  • Related