Просто назначьте все переменные и запишите результат одновременно.
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
их, но это кажется отрывочным.