Bash ?: foo () {echo “$ {var [0]}” içindeki muhtemel hata; }; var = (bar baz) foo


22

İşletim Sistemi : Ubuntu 16.04.3

Kabuk : Bash 4.3.48


Bunun geçici olarak bir değişkenin içeriğini değiştirmek mümkündür biliyorum var=value commandmuhtemelen olma, IFS= read -r varbunun en dikkate değer vaka.

Ve Greg'in wiki'si sayesinde şunu da anladım:

# Why this
foo() { echo "$var"; }
var=value foo

# And this does work
var=value; echo "$var"

# But this doesn't
var=value echo "$var"

Anlayışımdan kaçan şey şudur:

$ foo() { echo "${var[0]}"; }
$ var=(bar baz) foo
(bar baz)

Biliyorum (ve önceki örneklerin mantığı şu) Bildiğim kadarıyla, bu yazdırmalısınız bardeğil (bar baz).

Bu sadece bana olur mu? Bu amaçlanan davranış mı ve ben bir şey eksik? Yoksa bu bir böcek mi?


3
Belki de bash'ın çevresel değişkenler olarak dizileri desteklememesi ile ilgisi var?
Jesse_b,

3
@Jesse_b Belki. Koşarken export var=(foo bar); echo "${var[0]}"yazdırıyor foo, değil (foo bar).
nxnev

1
Tuhaf, bu benim için de işe yaradı. Ve exportbunu kullanarak gösterir:declare -ax var=([0]="foo" [1]="bar")
Jesse_b

3
Çevre dizileri içeremez, AFAIK. Örneğin, export i_am_array=(foo bar); /usr/bin/env | grep i_am_arrayburada hiçbir çıktı yok.
derobert

3
Ayrıca: foo() { declare -p var; } ; var=(bar baz) fooverir declare -x var="(bar baz)"onun bir dize olarak değil bir dizi tedavi edilen tasdik edici
derobert

Yanıtlar:


19

Genel olarak arayarak:

var=value cmd

cmdBir işlev taşınabilir değil nerede .

Bununla birlikte bash, yalnızca skaler değişkenler için çalışır (ve x=(...)bir dizi olarak ayrıştırılmış ancak skaler olarak atanmış) ve bunu yaparsanız, kapsam belirleme ile ilgili bir takım sorunlar vardır, ksh93ve ile yashçalışır, ancak değişken tanımı daha sonra kalır. İle mkshbir sözdizimi hatası alıyorsunuz. Bourne kabuğunda skaler değişkenler için bile işe yaramadı.

Ayrıca, skaler değişkenlerde bile, değişkenin işlev içinde dışa aktarılmasının (yani, yürütülen komutlara geçirilmesinin), kabuktan kabuğa (bash, yash, mksh, zsh içinde, ancak ksh cinsinden) değişmediğini unutmayın. kül).

Sadece beklediğiniz şekilde çalışır zsh. zshDizi indekslerinin 1'den başladığını unutmayın .

bash-4.4$ zsh
$ a=(before value)
$ f() echo $a[1]
$ a=(temp value) f
temp
$ echo $a[1]
before

12

Bu sadece bir hata değil, böyle bir şey yapma planları olmayan basit bir özellik gibi görünüyor. 2014'ten itibaren gönderilen bu posta listesi göndereninden aşağıdaki içerik oluşturuldu:

Neyse ki bash 4.3'te (patchlevel 25), sadece -DARRAY_EXPORT ve dizi değişkenini içe / dışa aktaramazsınız. Kod derlenmez ve eğer düzeltirseniz, link vermez ve onu düzeltirseniz, aşağıdaki sorunla sonuçlanırsınız.

Bu sadece bunun için geçmesi gereken bir ton sıkıntı. Dizi dışa aktarmayı etkinleştirmek için hiçbir planım yok.

Bash'in en son git repo'yu çekerek şunlara sahip variables.c:

  #  if ARRAY_EXPORT
        /* Array variables may not yet be exported. */

Her ne varsa tam olmadığını söyleyerek.


5
Burada, bir işlev için, bu nedenle herhangi bir execve()sistem çağrısı yapılmadığından herhangi bir şeyi dışa aktarma sorunu yoktur . zshGeçici olarak bu şekilde ayarlanan bir dizi ile arama işlevlerini destekleyen bir kabuk için bakın .
Stéphane Chazelas,

@ StéphaneChazelas Ancak çevre (yeni bir değişken ekleyerek) değişir ve işlev tamamlandıktan sonra geri döner (bu durum üzereyim:) my_var=one func_bar. Bunun exportçevreye katkıda bulunduğunu ve böylece ihracatın kaputun altında kullanıldığını söyleyebilir miyiz ? Cevabımı bak, gösteri kodunu ekledim.
MiniMax

10

Gönderen man bashbireyin HATALARI bölümünün (sürüm bash4.3 olduğunu):

BÖCEK

   Array variables may not (yet) be exported.

Bir sonraki kod, sadece fonksiyon çalışırken çevrede geçici bir değişken bulunduğunu gösterir. İşlev tamamlandığında geçici değişken kaybolur.

### defining the "bar" function
### it pass all environment variables to the "grep" command
### and the "grep" prints the only "my_var" variable from it
bar() { env | grep my_var=; }

### calls the "bar" function with the temporary 
### variable "my_var" created and assigned.
my_var=one bar

my_var=one         ### The output. The environment contains the "my_var" variable

### checks, does the environment still have the "my_var" variable
### (It doesn't have.)
env | grep my_var=
                   ### The output is empty,
                   ### the environment doesn't contain the "my_var" variable

İlgili bilgi:

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.