Возврат нескольких значений из функции в переменные с использованием скрипта bash - PullRequest
1 голос
/ 15 марта 2020

Я нашел следующий код для возврата нескольких переменных из функции в bash:

#!/bin/bash
calc()
{
  A=$1
  B=$2
  total=$(( A + B ))
  diff=$(( A - B ))
  echo "$total $diff"
}
read TOT DIF < <(calc 5 8)
echo $TOT
echo $DIF

Но когда я запускаю скрипт, я получаю следующее:

строка 10: синтаксическая ошибка рядом с неожиданным токеном `<'</p>

Есть идеи, как решить эту проблему? Я попробовал тот же код в консоли, и он работает, проблема в том, что я запускаю его из файла: sh myScript.sh.

Ответы [ 2 ]

3 голосов
/ 15 марта 2020

Вы могли бы сделать это альтернативным способом работы в не bash оболочке:

#!/bin/sh

calc()
{
  A="$1"
  B="$2"
  total=$(( A + B ))
  diff=$(( A - B ))
  # Return ASCII EOT (code 3) separated values
  printf '%d\3' "$total" "$diff"
}
# Configure the Internal Field Separator to ASCII 03 End Of Text
IFS="$(printf '\3')"
# shellcheck disable=SC2046 # Intentionally split values
# Sets the arguments from the returned string
set -- $(calc 5 8)
TOT="$1"
DIF="$2"
echo "$TOT"
echo "$DIF"

Один главный недостаток вызова функции calc в под-оболочке в аргументах set , - потеря кода возврата оболочки функции.

Это означает, что до calc функции приходится иметь дело с ошибочными ситуациями, такими как деление на ноль.

Например, : Он может включать код возврата в возвращенные значения, разделенные IFS.

Но это означает, что обработка ошибок намного сложнее.

Я бы не рекомендовал реализовывать несколько возвращаемых значений таким образом при отсутствии - bash shells.

Это все еще допустимый параметр для оболочки Bash для реализации множественного возврата в виде строки с разделителем EOT ASCII, поскольку код возврата оболочки сохраняется при чтении и разбиении возвращаемого значения. строка следующим образом:

#!/usr/bin/env bash

# Call calc and parse returned split string into values
IFS=$'\3' read -r TOT DIF < <(calc 5 3)
# Save calc's return-code
_rc="$?"

# The return-code from the calc function is preserved
# and can be tested
if [ $_rc -ne 0 ]; then
  printf 'calc failed with return-code %d\n' "$_rc" >&2
else
  echo "$TOT"
  echo "$DIF"
fi

2 голосов
/ 15 марта 2020

Вы явно запускаете его с sh myScript.sh. В этом случае шебанг #! игнорируется, потому что это комментарий к оболочке.

Шебанги обнаруживаются загрузчиком программы , не каждой отдельной оболочкой. Если бы вы запустили свою программу как ./myScript.sh (при условии, что она была помечена как исполняемая), загрузчик программы обнаружил бы shebang и автоматически преобразовал бы действие в /bin/bash myScript.sh.

Другими словами, либо используйте определите c оболочку, с которой вы хотите ее запустить (в данном случае это будет bash), или пусть загрузчик позаботится об этом (см. Предыдущий абзац).

Для Например, вот расшифровка вашего кода, выполняемого тремя различными методами (в частности, sh, в частности, bash, и позволяя загрузчику взять его на себя - только первый отказывает):

pax$ sh qq.sh
qq.sh: 10: qq.sh: Syntax error: redirection unexpected

pax$ bash qq.sh
13
-3

pax$ ./qq.sh
13
-3
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...