Просто назначьте все переменные и запишите результат одновременно.
f() { c= ; echo "${c:=$(date): $((a=3)) $((b=4))}" ; }
Теперь, если вы делаете:
f ; echo "$a $b $c"
Ваш вывод:
Tue Jul 1 04:58:17 PDT 2014: 3 4
3 4 Tue Jul 1 04:58:17 PDT 2014: 3 4
Обратите внимание, что это полностью переносимый код POSIX. Я первоначально установлен c=на ''строку с нулевым символом , поскольку расширение параметр ограничивает одновременное задание переменной + оценку либо только числовые (например $((var=num))) или с нулевыми или несуществующих значений - или, другими словами, вы не можете одновременно установить и оценить переменную для произвольной строки если этой переменной уже присвоено значение. Поэтому я просто проверяю, что он пуст, прежде чем пытаться. Если бы я не опустел cдо того, как попытаться назначить его, расширение вернуло бы только старое значение.
Просто чтобы продемонстрировать:
sh -c '
c=oldval a=1
echo ${c:=newval} $((a=a+a))
'
###OUTPUT###
oldval 2
newvalэто не назначается $cрядный , потому что oldvalрасширяется в ${word}, в то время как рядный $((арифметическое =задание ))всегда происходит. Но если $c не имеет oldval и пусто или не установлено ...
sh -c '
c=oldval a=1
echo ${c:=newval} $((a=a+a))
c= a=$((a+a))
echo ${c:=newval} $((a=a+a))
'
###OUTPUT###
oldval 2
newval 8
... тогда newvalсразу назначается и расширяется в $c.
Все другие способы сделать это включают некоторую форму вторичной оценки. Например, скажем, я хотел назначить вывод f()переменной, названной nameв одной точке и varв другой. Как написано в настоящее время, это не будет работать без установки переменной var в области действия вызывающего. Другой способ может выглядеть так:
f(){ fout_name= fout= set -- "${1##[0-9]*}" "${1%%*[![:alnum:]]*}"
(: ${2:?invalid or unspecified param - name set to fout}) || set --
export "${fout_name:=${1:-fout}}=${fout:=$(date): $((a=${a:-50}+1)) $((b=${b:-100}-4))}"
printf %s\\n "$fout"
}
f &&
printf %s\\n \
"$fout_name" \
"$fout" \
"$a" "$b"
Ниже приведен лучший форматированный пример, но, как указано выше, вывод выглядит так:
sh: line 2: 2: invalid or unspecified param - name set to fout
Wed Jul 2 02:27:07 PDT 2014: 51 96
fout
Wed Jul 2 02:27:07 PDT 2014: 51 96
51
96
Или с разными $ENVаргументами:
b=9 f myvar &&
printf %s\\n \
"$fout_name" \
"$fout" \
"$myvar" \
"$a" "$b"
###OUTPUT###
Tue Jul 1 19:56:42 PDT 2014: 52 5
myvar
Tue Jul 1 19:56:42 PDT 2014: 52 5
Tue Jul 1 19:56:42 PDT 2014: 52 5
52
5
Вероятно, самая сложная вещь, которую нужно сделать правильно, когда дело доходит до двукратной оценки, - убедиться, что переменные не разбивают кавычки и не выполняют случайный код. Чем больше раз оценивается переменная, тем сложнее она становится. Расширение параметров здесь очень помогает, и использование exportв отличие от evalнего намного безопаснее.
В приведенном выше примере f()первый назначает $foutна ''строку с нулевым символом , а затем устанавливает позиционные Params испытанию для допустимых имен переменных. Если оба теста не пройдены, отправляется сообщение stderrи foutназначается значение по умолчанию $fout_name. Однако независимо от тестов $fout_nameвсегда присваивается либо foutуказанное вами имя, либо, $foutи, опционально, указанному имени всегда присваивается выходное значение функции. Чтобы продемонстрировать это, я написал этот маленький forцикл:
for v in var '' "wr;\' ong"
do sleep 10 &&
a=${a:+$((a*2))} f "$v" || break
echo "${v:-'' #null}"
printf '#\t"$%s" = '"'%s'\n" \
a "$a" b "$b" \
fout_name "$fout_name" \
fout "$fout" \
'(eval '\''echo "$'\''"$fout_name"\")' \
"$(eval 'echo "$'"$fout_name"\")"
done
Он играет с именами переменных и расширениями параметров. Если у вас есть вопрос, просто спросите. Это только запускает те же несколько строк в функции, уже представленной здесь. Стоит отметить , по крайней мере , хотя , что $aи $bпеременные ведут себя по- разному в зависимости от того, являются ли они определены при вызове, или установить уже. Тем forне менее, они почти ничего не делают, кроме как форматируют набор данных и предоставляют f(). Посмотри:
###OUTPUT###
Wed Jul 2 02:50:17 PDT 2014: 51 96
var
# "$a" = '51'
# "$b" = '96'
# "$fout_name" = 'var'
# "$fout" = 'Wed Jul 2 02:50:17 PDT 2014: 51 96'
# "$(eval 'echo "$'"$fout_name"\")" = 'Wed Jul 2 02:50:17 PDT 2014: 51 96'
sh: line 2: 2: invalid or unspecified param - name set to fout
Wed Jul 2 02:50:27 PDT 2014: 103 92
'' #null
# "$a" = '103'
# "$b" = '92'
# "$fout_name" = 'fout'
# "$fout" = 'Wed Jul 2 02:50:27 PDT 2014: 103 92'
# "$(eval 'echo "$'"$fout_name"\")" = 'Wed Jul 2 02:50:27 PDT 2014: 103 92'
sh: line 2: 2: invalid or unspecified param - name set to fout
Wed Jul 2 02:50:37 PDT 2014: 207 88
wr;\' ong
# "$a" = '207'
# "$b" = '88'
# "$fout_name" = 'fout'
# "$fout" = 'Wed Jul 2 02:50:37 PDT 2014: 207 88'
# "$(eval 'echo "$'"$fout_name"\")" = 'Wed Jul 2 02:50:37 PDT 2014: 207 88'
$aи$bявляются локальными переменными в вашейfфункции. Вы могли быexportих, но это кажется отрывочным.