Search code examples
bashmathbcsubshell

Assign the result of a mathematical calculation to a variable without a subshell


My question is a twofold.

First:

Is it possible to achieve this without using a subshell?

FOO=$((6-5))

or this?

BAR=`echo "$FOO/100" | bc -l`

If I understand the second one correctly, I'm creating 2 subshells by using ´ and |

Second

Does creating/using subshells for this kind of stuff impact the overall performance of a script?

-- Thanks


Solution

  • You can check count of subprocess allocated with that simple line:

    bash -c 'echo $$'
    

    It create new shell and outputs current process id.

    Since processes in linux are sequential numbers, we can use this "hack" to detect how many processes was started between commands. (some processes can be started in background by cron or at, so need to check results multiple times).

    Also this command will start process, so if you start it multiple time you will see increasing number. To get real count of processes that was started between this command you must substract 1.

    So starting checking.

    $ bash -c 'echo $$'
    4240
    $ FOO=$((6-5))
    $ bash -c 'echo $$'
    4241
    

    4241 - 4240 - 1 = 0. No subprocess was started.

    $ FOO=1111
    $ bash -c 'echo $$'
    4244
    $ BAR=`echo "$FOO/100" | bc -l`
    $ bash -c 'echo $$'
    4248
    

    4248 - 4244 - 1 = 3. There is 3 process was started.

    If we start with "here is a string" removing useless echo:

    $ bash -c 'echo $$'
    4256
    $ BAR=`bc -l <<< "$FOO/100"`
    $ bash -c 'echo $$'
    4259
    

    4259 - 4256 - 1 = 2. Now 2 subprocess was started.

    seems like echo implicitly allocates new shell??

    1. backticks allocates new shell - new process to read output

    2. bc allocates new process

    This variant will create two subprocess too:

    read BAR < <(bc -l <<< "$FOO / 100")
    
    1. read is a bash command - it does not fork subprocess and executed in the same shell

    2. () will create shell - subprocess

    3. bc will create subprocess