ti-enxame.com

No bash, como armazenar um valor de retorno em uma variável?

Conheço alguns comandos muito básicos no Linux e estou tentando escrever alguns scripts. Eu escrevi uma função que avalia a soma dos últimos 2 dígitos em um número de 5 dígitos. A função deve concatenar essa soma resultante entre os últimos 2 dígitos e retorná-la. O motivo pelo qual desejo retornar esse valor é porque usarei esse valor na outra função.

Ex: se eu tiver 12345, minha função calculará 4 + 5 e retornará 495.

#!/bin/bash

set -x
echo "enter: "
        read input

function password_formula
{
        length=${#input}
        last_two=${input:length-2:length}
        first=`echo $last_two| sed -e 's/\(.\)/\1 /g'|awk '{print $2}'`
        second=`echo $last_two| sed -e 's/\(.\)/\1 /g'|awk '{print $1}'`
        let sum=$first+$second
        sum_len=${#sum}
        echo $second
        echo $sum

        if [ $sum -gt 9 ]
        then
               sum=${sum:1}
        fi

        value=$second$sum$first
        return $value
}
result=$(password_formula)
echo $result

Estou tentando ecoar e ver o resultado, mas estou obtendo a saída conforme mostrado abaixo.

-bash-3.2$ ./file2.sh 
+++ password_formula
+++ echo 'enter: '
+++ read input
12385
+++ length=8
+++ last_two=85
++++ echo 85
++++ sed -e 's/\(.\)/\1 /g'
++++ awk '{print $2}'
+++ first=5
++++ echo 85
++++ sed -e 's/\(.\)/\1 /g'
++++ awk '{print $1}'
+++ second=8
+++ let sum=5+8
+++ sum_len=2
+++ echo 5
+++ echo 8
+++ echo 13
+++ '[' 13 -gt 9 ']'
+++ sum=3
+++ value=835
+++ return 835
++ result='enter: 
5
8
13'
++ echo enter: 5 8 13
enter: 5 8 13

Eu também tentei imprimir o resultado como:

password_formula
RESULT=$?
echo $RESULT

Mas isso está dando algum valor desconhecido:

++ RESULT=67
++ echo 67
67

Como posso armazenar corretamente o valor correto e imprimir (para verificar novamente) na tela?

Desde já, obrigado.

32
itsh

O valor de retorno (também conhecido como código de saída) é um valor no intervalo de 0 a 255, inclusive. É usado para indicar sucesso ou fracasso, não para retornar informações. Qualquer valor fora desse intervalo será quebrado.

Para retornar informações, como seu número, use

echo "$value"

Para imprimir informações adicionais que você não deseja capturar, use

echo "my irrelevant info" >&2 

Por fim, para capturá-lo, use o que você fez:

 result=$(password_formula)

Em outras palavras:

echo "enter: "
        read input

password_formula()
{
        length=${#input}
        last_two=${input:length-2:length}
        first=`echo $last_two| sed -e 's/\(.\)/\1 /g'|awk '{print $2}'`
        second=`echo $last_two| sed -e 's/\(.\)/\1 /g'|awk '{print $1}'`
        let sum=$first+$second
        sum_len=${#sum}
        echo $second >&2
        echo $sum >&2

        if [ $sum -gt 9 ]
        then
               sum=${sum:1}
        fi

        value=$second$sum$first
        echo $value
}
result=$(password_formula)
echo "The value is $result"
23
that other guy

Resposta mais simples:

o código de retorno de uma função pode ser apenas um valor no intervalo de 0 a 255. Para armazenar esse valor em uma variável, você deve fazer o seguinte neste exemplo:

#!/bin/bash

function returnfunction {
    # example value between 0-255 to be returned 
    return 23
}

# note that the value has to be stored immediately after the function call :
returnfunction
myreturnvalue=$?

echo "myreturnvalue is "$myreturnvalue
11
Samuele Catuzzi

É fácil você precisar ecoar o valor que precisa retornar e capturá-lo como abaixo

demofunc(){
    local variable="hellow"
    echo $variable    
}

val=$(demofunc)
echo $val
6
imal hasaranga perera

Use a variável especial do bash "$?" igual a:

function_output=${my_function}
function_return_value=$?
4
Ytsen de Boer

A resposta acima sugere alterar a função para ecoar dados, em vez de retorná-los para que possam ser capturados.

Para uma função ou programa que você não pode modificar onde o valor de retorno precisa ser salvo em uma variável (como test/[, que retorna um valor de 0/1 de sucesso), echo $? dentro da substituição de comando:

# Test if we're remote.
isRemote="$(test -z "$REMOTE_ADDR"; echo $?)"
# Or:
isRemote="$([ -z "$REMOTE_ADDR" ]; echo $?)"

# Additionally you may want to reverse the 0 (success) / 1 (error) values
# for your own sanity, using arithmetic expansion:
remoteAddrIsEmpty="$([ -z "$REMOTE_ADDR" ]; echo $((1-$?)))"

Por exemplo.

$ echo $REMOTE_ADDR

$ test -z "$REMOTE_ADDR"; echo $?
0
$ REMOTE_ADDR=127.0.0.1
$ test -z "$REMOTE_ADDR"; echo $?
1
$ retval="$(test -z "$REMOTE_ADDR"; echo $?)"; echo $retval
1
$ unset REMOTE_ADDR
$ retval="$(test -z "$REMOTE_ADDR"; echo $?)"; echo $retval
0

Para um programa que imprime dados, mas também possui um valor de retorno a ser salvo, o valor de retorno seria capturado separadamente da saída:

# Two different files, 1 and 2.
$ cat 1
1
$ cat 2
2
$ diffs="$(cmp 1 2)"
$ haveDiffs=$?
$ echo "Have differences? [$haveDiffs] Diffs: [$diffs]"
Have differences? [1] Diffs: [1 2 differ: char 1, line 1]
$ diffs="$(cmp 1 1)"
$ haveDiffs=$?
$ echo "Have differences? [$haveDiffs] Diffs: [$diffs]"
Have differences? [0] Diffs: []

# Or again, if you just want a success variable, reverse with arithmetic expansion:
$ cmp -s 1 2; filesAreIdentical=$((1-$?))
$ echo $filesAreIdentical
0
4
Calpau

É devido às instruções echo. Você pode mudar seus ecos para impressões e retornar com um echo. Obras abaixo

#!/bin/bash

set -x
echo "enter: "
read input

function password_formula
{
        length=${#input}
        last_two=${input:length-2:length}
        first=`echo $last_two| sed -e 's/\(.\)/\1 /g'|awk '{print $2}'`
        second=`echo $last_two| sed -e 's/\(.\)/\1 /g'|awk '{print $1}'`
        let sum=$first+$second
        sum_len=${#sum}
        print $second
        print $sum

        if [ $sum -gt 9 ]
        then
           sum=${sum:1}
        fi

        value=$second$sum$first
        echo $value
}
result=$(password_formula)
echo $result
0
Kat Farrell