Search code examples
gnu-parallel

GNU Parallel with sequence number `{#}` and `-n` option


Using GNU Parallel 20210222 with --rpl '{0#} $_=sprintf("%02d",$job->seq())' in my ~/.parallel/config, why does

seq 256 | parallel -n 64 echo {0#}

output

01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02
03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03
04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04 04

and not

01
02
03
04

whereas

seq 256 | parallel -n 64 echo {#}

outputs

1
2
3
4

?


Solution

  • It is hardly surprising that this:

    seq 10 | parallel -n 5 echo '{= $_=-$_ =}'
    

    gives the same as this:

    seq 10 | parallel --rpl '{-} $_=-$_' -n 5 echo {-}
    

    namely:

    -1 -2 -3 -4 -5
    -6 -7 -8 -9 -10
    

    You can make {-} into a positional replacement string by prepending with the number of the argument to be replaced:

    seq 10 | parallel --rpl '{-} $_=-$_' -n 5 echo {1-} {3-} {5-}
    

    which gives:

    -1 -3 -5
    -6 -8 -10
    

    The positionality can be be part of the definition:

    seq 10 | parallel --rpl '{-} 1 $_=-$_' -n 5 echo {-}
    

    which gives:

    -1
    -6
    

    {#} is defined in the source code as:

         '{#}'  => '1 $_=$job->seq()',
    

    So this is a positional replacement string and will only be replaced for the first value.

    This

    {0#} $_=sprintf("%02d",$job->seq())
    

    is not a positional replacement string, but an ordinary replacement string that will be replaced for each input.

    But it can easily be changed into a positional one:

    seq 256 | parallel --rpl '{0#} 1 $_=sprintf("%02d",$job->seq())' -n 64 echo {0#}
    seq 256 | parallel --rpl '{0#} $_=sprintf("%02d",$job->seq())' -n 64 echo {10#}
    

    The last one looks a little confusing, but that is because we as humans will see '10' and not '1' (the input number) followed by '0#'.