Chỉ cần gán tất cả các biến và viết đầu ra cùng một lúc.
f() { c= ; echo "${c:=$(date): $((a=3)) $((b=4))}" ; }
Bây giờ nếu bạn làm:
f ; echo "$a $b $c"
Đầu ra của bạn là:
Tue Jul 1 04:58:17 PDT 2014: 3 4
3 4 Tue Jul 1 04:58:17 PDT 2014: 3 4
Lưu ý rằng đây là mã di động POSIX đầy đủ. Tôi bước đầu thiết lập c=
đến ''
chuỗi null vì mở rộng tham số hạn chế chuyển nhượng biến đồng thời + đánh giá cho một trong hai chỉ số (như $((var=num))
) hoặc từ null hoặc không tồn tại giá trị - hoặc, nói cách khác, bạn có thể không được kiêm nhiệm thiết lập và đánh giá một biến cho một chuỗi tùy ý nếu biến đó đã được gán một giá trị. Vì vậy, tôi chỉ đảm bảo rằng nó trống trước khi thử. Nếu tôi không trống c
trước khi cố gắng gán nó, việc mở rộng sẽ chỉ trả về giá trị cũ.
Chỉ để chứng minh:
sh -c '
c=oldval a=1
echo ${c:=newval} $((a=a+a))
'
###OUTPUT###
oldval 2
newval
là không giao cho $c
inline vì oldval
được mở rộng sang ${word}
, trong khi các inline $((
số học =
phân ))
luôn luôn xảy ra. Nhưng nếu $c
không có oldval
và trống hoặc không đặt ...
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
... sau đó newval
ngay lập tức được gán và mở rộng thành $c
.
Tất cả các cách khác để làm điều này liên quan đến một số hình thức đánh giá thứ cấp. Ví dụ: giả sử tôi muốn gán đầu ra f()
cho một biến có tên name
tại một điểm và var
tại một điểm khác. Như được viết hiện tại, điều này sẽ không hoạt động mà không đặt var trong phạm vi của người gọi. Một cách khác có thể trông như thế này, mặc dù:
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"
Tôi đã cung cấp một ví dụ được định dạng tốt hơn bên dưới, nhưng, được gọi như trên đầu ra là:
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
Hoặc với các $ENV
đối số hoặc đối số khác nhau :
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
Có lẽ điều khó nhất để có được đúng khi đánh giá hai lần là đảm bảo rằng các biến không phá vỡ dấu ngoặc kép và thực thi mã ngẫu nhiên. Càng nhiều lần một biến được đánh giá càng khó. Mở rộng tham số giúp rất nhiều ở đây, và sử dụng export
trái ngược với eval
an toàn hơn nhiều.
Trong ví dụ trên f()
đầu tiên gán $fout
các ''
chuỗi rỗng và sau đó đặt params vị trí để kiểm tra cho tên biến hợp lệ. Nếu cả hai bài kiểm tra không vượt qua, một thông báo sẽ được phát ra stderr
và giá trị mặc định fout
được gán cho $fout_name
. Tuy nhiên, bất kể các thử nghiệm $fout_name
luôn được gán cho một fout
hoặc tên bạn chỉ định $fout
và, tùy ý, tên được chỉ định của bạn luôn được gán giá trị đầu ra của hàm. Để chứng minh điều này tôi đã viết for
vòng lặp nhỏ này :
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
Nó chơi xung quanh một số với tên biến và mở rộng tham số. Nếu bạn có một câu hỏi, hãy hỏi. Điều đó chỉ chạy cùng một vài dòng trong hàm đã được trình bày ở đây. Ít nhất nên đề cập đến việc mặc dù rằng các biến $a
và $b
hành vi khác nhau tùy thuộc vào việc chúng được xác định tại lệnh gọi hay đã được đặt. Tuy nhiên, for
hầu như không có gì ngoài định dạng tập dữ liệu và được cung cấp bởi f()
. Có một cái nhìn:
###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
và$b
là các biến cục bộ trongf
hàm của bạn . Bạn có thểexport
họ, nhưng điều đó có vẻ sơ sài.