Detailed Explanation of the Return Value Problem of Processing Method in Shell

Time:2019-8-11

background

Nowadays, programmers who don’t know Linux don’t mean to say they are programmers, and those who don’t know shell programming can’t say they know Linux. With shell programming, when writing tools for batch processing, you often need to customize functions. In more complex cases, it may be necessary to return a value.

Because in the shell world, unlike other programming languages, it does not support methods that we are familiar with returning. This article summarizes how to solve the return value problem gracefully.

Test program

We usually get the output of the last statement through $? Look at the following test statements:

New testReturn script


returnString(){
 return $1
}
returnString $1
result=$?
echo "result=$result"

Now we have a testReturn script with a return String method, which we hope will return directly the parameters we entered.
When we take hello, 500, 12 as input parameters, are their execution and output the same?


./testReturn hello
./testReturn 500
./testReturn 12

In mind, try to guess the possible situation. Now let’s reveal the answer:

Program Output

When Hello is executed, instead of outputting hello, an error is reported that returns only accept numeric types.


aven-mac-pro-2:avenwu.github.io aven$ ./testReturn hello
./testReturn: line 23: return: hello: numeric argument required
result=255

When 500 is executed, the page does not output 500, but 244.


aven-mac-pro-2:avenwu.github.io aven$ ./testReturn 500
result=244

At the time of execution 12, finally correct, return 12


aven-mac-pro-2:avenwu.github.io aven$ ./testReturn 12
result=12

Anomaly analysis

Now let’s analyze the return String method. Why are there so many output cases?

First of all, his writing is obviously not rigorous, but it is not entirely wrong, such as typing 12, he returned correctly.

Return itself is the buildin function in the shell. The author summarizes the following characteristics:

  • Return can return a numeric state, often used to return 0, 1, indicating whether a function has been successfully executed
  • Note that return cannot return non-numeric types
  • At the same time, digital types may also overflow.

global variable

What if we just want to return a string? We can assign values by defining global variables, similar to static variables / member variables, so that their scope can penetrate the whole context.


result=""
returnString(){
 result=$1
}
returnString $1
echo "result=$result"

Looking at the output again, we get the results we need:


aven-mac-pro-2:avenwu.github.io aven$ ./testReturn hello
result=hello
aven-mac-pro-2:avenwu.github.io aven$ ./testReturn 500
result=500
aven-mac-pro-2:avenwu.github.io aven$ ./testReturn 12
result=12

However, writing this way will pollute the global variables, and the result variable can easily be modified both internally and externally, leading to the failure of internal modifications.

eval

In addition to return, there are other keywords for buildin, such as eval, local.

By default, the variables defined in the current script are global variables, while in the method, local variables can be defined to avoid global variable pollution.
At the same time, it combines Eval assignment statement to modify variables.


returnString(){
 local __result=$2
 eval $__result=$1
}
returnString $1 result
echo "result=$result"

Similarly, we have achieved the desired results.


aven-mac-pro-2:avenwu.github.io aven$ ./testReturn hello
result=hello
aven-mac-pro-2:avenwu.github.io aven$ ./testReturn 500
result=500
aven-mac-pro-2:avenwu.github.io aven$ ./testReturn 12
result=12

echo

Finally, a method is introduced, which combines command substitution with echo output.

The command substitution also failed to find a suitable translation, let’s translate the command literally.

If you have only one echo output inside your method, you can also use it to make it worthwhile to return, but this has some limitations. Make sure that there is only one echo output in your method, otherwise there will be too much assignment.

returnString(){
 local __result=$1
 echo $__result
}
# Or result=`return String $1`
result=$(returnString $1)
echo "result=$result"

Expected results can also be obtained.


aven-mac-pro-2:avenwu.github.io aven$ ./testReturn hello
result=hello
aven-mac-pro-2:avenwu.github.io aven$ ./testReturn 500
result=500
aven-mac-pro-2:avenwu.github.io aven$ ./testReturn 12
result=12

Cross-border issues

Now that we have several ways to return strings, why are returned numbers sometimes correct and sometimes incorrect?

We know that return is originally used to return execution status, such as 0, 1. So when we return 500, we actually overflow data.

According to the test, we infer that the shell’s built-in return acceptance return value uses a byte size, that is, 8 bits, which can output an unsigned 0-255 shaping at most, and all the data outside the scope is overflowed. So when using return, be sure to pay attention to the value size.

Summary

It’s easy to write small scripts with shell commands, but if you encounter complex logic, it’s advisable to use other more appropriate previews, such as Python, Golang and so on.

summary

Above is the whole content of this article. I hope that the content of this article has a certain reference value for everyone’s study or work. If you have any questions, you can leave a message and exchange it. Thank you for your support to developpaer.

Recommended Today

Implementation of PHP Facades

Example <?php class RealRoute{ public function get(){ Echo’Get me’; } } class Facade{ public static $resolvedInstance; public static $app; public static function __callStatic($method,$args){ $instance = static::getFacadeRoot(); if(!$instance){ throw new RuntimeException(‘A facade root has not been set.’); } return $instance->$method(…$args); } // Get the Facade root object public static function getFacadeRoot() { return static::resolveFacadeInstance(static::getFacadeAccessor()); } protected […]