linuxbashshellbrace-expansion

Create sequence from literal variable inputs


I'm trying to create sequences as follows:

startDay=1
endDay=2
dayRange="{$startDay..$endDay}"
echo \[\"$dayRange\",\"{00..02}\"\]

The output is:

["{1..2}","00"] ["{1..2}","01"] ["{1..2}","02"]

When specifying the sequence directly {00..02}, it auto creates "00", "01", "02", but it does not understand the dayRange variable. What I expect it to return is:

["1","00"] ["1","01"] ["1","02"] ["2","00"] ["2","01"] ["2","02"] 

Not sure what I missed. Please advise.


Solution

  • First idea would be a simple nested for loop:

    startDay=1
    endDay=2
    
    pfx=
    out=
    
    for ((i=startDay; i<=endDay; i++))
    do
        for j in {00..02}
        do
             out+="${pfx}[\"${i}\",\"${j}\"]"
             pfx=" "
        done
    done
    
    echo "${out}"
    

    This generates:

    ["1","00"] ["1","01"] ["1","02"] ["2","00"] ["2","01"] ["2","02"]
    

    A bit less coding, and a bit faster, which uses OP's echo ... {00..02} to eliminate one of the for loops:

    NOTE: this eliminates the subprocess $(echo ...) call I had in a previous edit.

    startDay=1
    endDay=2
    
    for ((i=startDay; i<=endDay; i++))
    do
        echo -n "[\""${i}"\",\""{00..02}"\"]"
        echo -n " "
    done
    
    echo ""
    

    This also generates:

    ["1","00"] ["1","01"] ["1","02"] ["2","00"] ["2","01"] ["2","02"]
    

    Here's one awk idea:

    awk -v start=$"${startDay}" -v end="${endDay}" '
    BEGIN {
        pfx=""
        out=""
    
        for (i=start; i<=end; i++)
            for (j=0; j<=2; j++) {
                 out=out pfx "[\"" i "\",\"" sprintf("%02d", j) "\"]"
                 pfx=" "
            }
        print out
    }'
    

    This also generates:

    ["1","00"] ["1","01"] ["1","02"] ["2","00"] ["2","01"] ["2","02"]
    

    With the elimination of the earlier subprocess $(echo ...) the first 2 solutions come in with single-digit millisecond timings while the awk solution comes in with low double-digit millisecond timings.

    As the number of days (and/or sequence size) increases the first 2 solutions start taking longer (the nested for loop falling farther behind) while the awk solution tends to maintain the same speed.

    For really large increases (number of days and/or sequence size) I would expect awk to close in on, and eventually take, the lead.