Mengekspor variabel dengan titik (.) Di dalamnya

39

Cara mengekspor variabel yang memiliki titik di dalamnya. Saya mendapatkan 'nama variabel tidak valid' ketika saya mencoba:

 export my.home=/tmp/someDir
-ksh: my.home=/tmp/someDir: invalid variable name

Bahkan menghindari metacharacter dot (.) Juga tidak membantu

$ export my\.home=/tmp/someDir
export: my.home=/tmp/someDir: is not an identifier
pengguna1587504
sumber
1
sayangnya itu tidak terdaftar ketika saya mengetik / mencari pertanyaan serupa. Maaf. ..
user1587504

Jawaban:

50

Paling tidak untuk bashhalaman manual mendefinisikan sintaks ekspor sebagai:

export [-fn] [name[=word]] ...

Itu juga mendefinisikan "nama" sebagai:

   name   A  word  consisting  only  of alphanumeric characters and under
          scores, and beginning with an alphabetic character or an  under
          score.  Also referred to as an identifier.

Karenanya Anda benar-benar tidak dapat mendefinisikan variabel seperti my.homeitu karena tidak ada pengidentifikasi yang valid.

Saya sangat yakin ksh Anda memiliki definisi pengidentifikasi yang sangat mirip dan karenanya tidak mengizinkan variabel semacam ini juga. (Lihatlah halaman manualnya.)

Saya juga sangat yakin ada semacam standar umum (POSIX?) Yang menentukan, apa yang diizinkan sebagai pengidentifikasi (dan karena itu nama variabel).


Jika Anda benar-benar membutuhkan variabel semacam ini untuk beberapa alasan, Anda dapat menggunakan sesuatu seperti

env "my.home=/tmp/someDir" bash

untuk mendefinisikannya. Tetapi sekali lagi, Anda tidak akan dapat mengaksesnya menggunakan sintaksis shell normal. Dalam hal ini Anda mungkin perlu bahasa lain seperti perl:

perl -e 'print $ENV{"my.home"}'

Sebagai contoh

env "my.home=/tmp/someDir" perl -le 'print $ENV{"my.home"}'

harus mencetak jalur Anda.

michas
sumber
Itu karena dalam integrasi semut. Dan sayangnya itu tidak memungkinkan untuk mengatur / mengekspor variabel dari unix. Menerima jawaban Anda. ..
user1587504
1
semut biasanya dikonfigurasikan oleh variabel lingkungan tunggal yang dipanggil ANT_OPTSatau oleh ~ / .antrc. Tidak perlu nama variabel lingkungan aneh untuk semut itu sendiri.
michas
8

Sementara variabel lingkungan dapat memiliki nama apa pun (termasuk string kosong) yang tidak mengandung tanda yang sama atau byte nol, variabel shell memetakan variabel lingkungan ke variabel shell dan di sebagian besar shell, nama variabel terbatas pada karakter alfanumerik ASCII dan di _mana karakter pertama dapat ' t menjadi digit (kecuali untuk parameter posisi dan orang-orang khusus lainnya seperti $*, $-, $@, ..., (yang tidak dipetakan ke variabel lingkungan yang sesuai)). Perhatikan juga bahwa beberapa variabel dicadangkan / khusus oleh / ke shell.

Pengecualian untuk itu:

  • The rcshell dan turunannya seperti esdan akangamendukung nama apapun kecuali string kosong, dan mereka yang semua-numerik atau berisi =karakter (dan selalu mengekspor semua variabel terhadap lingkungan, dan waspadalah terhadap variabel khusus seperti *, status, pid...):

    ; '%$£"' = test
    ; echo $'%$£"'
    test
    ; '' = x
    zero-length variable name
    ;

    Namun, ia menggunakan pengodeannya sendiri untuk variabel yang namanya tidak mengandung alnums atau untuk array ketika diteruskan dalam lingkungan perintah yang dijalankan:

    $ rc -c '+ = zzz; __ = zzz; a = (zzz xxx); env' | sed -n /zzz/l
    __2b=zzz$
    __5f_=zzz$
    a=zzz\001xxx$
    $ env +=x rc -c "echo $'+'"
    x
    $ env __2b=x rc -c "echo $'+'"
    x
  • AT&T ksh, yashdan zsh(juga bashtetapi hanya untuk karakter bita tunggal) mendukung alnum di lokal saat ini, tidak hanya yang ASCII.

    $ Stéphane=1
    $ echo "$Stéphane"
    1

    Dalam shell itu, Anda bisa mengubah lokal untuk menganggap sebagian besar karakter sebagai alpha, tetapi tetap saja itu tidak akan berfungsi untuk karakter ASCII .. Anda dapat membodohi zshatau kshberpikir £adalah sebuah huruf, tetapi bukan itu .atau karakter ASCII lainnya (di mana memungkinkan karakter dalam nama variabel yang bersangkutan, bukan untuk [[:alpha:]]glob misalnya).

  • ksh93memiliki variabel khusus yang namanya mengandung titik seperti ${.sh.version}, tetapi variabel tersebut tidak dipetakan ke variabel lingkungan dan khusus. Ini .untuk memastikan tidak bertentangan dengan variabel lain. Jika telah memilih untuk menyebutnya $sh_version, maka bisa berpotensi rusak script yang digunakan bahwa variabel sudah (lihat misalnya bagaimana zshmemiliki masalah dengan nya $pathatau $commandsvariabel array / hash khusus (a la csh) yang memecah beberapa script).

Perhatikan bahwa selain cangkang yang tidak mendukung variabel-variabel tersebut, beberapa cangkang seperti pdksh / mksh memang menghapusnya dari lingkungan yang mereka terima ( bashmenghapus yang dengan nama kosong ash,, kshdan bashmenghapus string lingkungan yang tidak mengandung =karakter):

$ env %%%=test 1=%%% a.b=%%% mksh -c env | grep %%%
$ env %%%=test 1=%%% a.b=%%% bash -c env | grep %%%
%%%=test
a.b=%%%
1=%%%

$ perl -le '$ENV{""}="%%%"; exec "bash", "-c", "env"' | grep %%%
$ perl -le '$ENV{""}="%%%"; exec "zsh", "-c", "env"' | grep %%%
=%%%

$ echo 'main(){char*a[]={"sh","-c","env",0};char*e[]={"%%%",0};
    execve("/bin/ash",a,e);}'|tcc -run - | grep %%%
$ echo 'main(){char*a[]={"sh","-c","env",0};char*e[]={"%%%",0};
    execve("/bin/zsh",a,e);}'|tcc -run - | grep %%%
%%%

Singkatnya, yang terbaik adalah untuk tetap dengan nama variabel didukung oleh sebagian besar kerang dan bahkan mencoba untuk menggunakan huruf untuk variabel lingkungan (dan menurunkan kasus atau kasus campuran untuk variabel shell tidak diekspor) menghindari orang-orang yang khusus dalam kerang (seperti IFS, PS1, BASH_VERSION...).

Jika Anda perlu mengatur variabel seperti itu di shell yang tidak mendukungnya, tetapi tidak membuangnya, Anda bisa mengeksekusi ulang diri sendiri, dengan sesuatu seperti:

#! /bin/ksh -
perl -e 'exit 1 unless defined($ENV{"a.b"})' || exec env a.b=%%% "$0" "$@"

(tentu saja, jika Anda perlu melakukannya di tengah-tengah skrip, itu tidak akan membantu, tetapi Anda kemudian bisa melihat pendekatan itu untuk menyimpan dan mengembalikan lingkungan eksekusi shell melalui re-exec). Atau coba pendekatan debugger:

gdb --batch-silent -ex 'call putenv("a.b=%%%")' --pid="$$"

(yang satu tampaknya bekerja dengan zsh, yash, cshdan tcshpada amd64 Linux, tapi tidak dengan salah satu kerang lain saya mencoba ( mksh, ksh93, bash, dash)).

Stéphane Chazelas
sumber
1
mksh(dan pdksh) memang membangun proses lingkungan yang mereka hasilkan sepenuhnya dari awal, hanya menggunakan parameter yang diekspor dalam lingkungan eksekusi shell saat ini, sehingga tidak ada cara untuk melewatkan variabel-variabel tersebut melalui shell tersebut. (Catatan bahwa variabel yang sedang berlalu tunduk pada perubahan, misalnya saya berencana untuk dukungan ekspor array untuk mkshbeberapa hari.)
mirabilos
0

Seperti yang ditunjukkan oleh posting lain, shell yang paling umum tidak memungkinkan untuk mengatur variabel lingkungan dengan periode pada namanya. Namun, saya telah menemukan situasi, terutama yang melibatkan Docker dan program yang dijalankan, di mana perangkat lunak membutuhkan nilai-nilai kunci dengan periode.

Namun, dalam masing-masing situasi ini, pasangan nilai kunci tersebut dapat diteruskan ke program melalui cara lain selain variabel lingkungan. Misalnya, di Ant, Anda dapat menggunakan "-propertyfile (nama file)" untuk meneruskan dalam file properti yang diformat kumpulan nilai-nilai kunci. Confd memungkinkan untuk "-mengembalikan file -file (file yaml)".

Saya melewati variabel lingkungan dalam bentuk "C__any_value = 'my.property.key = the value'". Saya kemudian mengalihkan permintaan program untuk pertama-tama menghasilkan file:

set | awk -- 'BEGIN { FS="'\''" } /^C__/ {print $2}' > my-key-values.txt

The setperintah, di Borne Shell, akan menampilkan masing-masing properti pada baris terpisah dalam bentuk

C__any_value='my.property.key=the value'

The awkperintah hanya akan memproses variabel lingkungan dimulai dengan C__, kemudian ekstrak nilai-nilai yang terkandung dalam tanda kutip tunggal.

Metode ini mensyaratkan nilai variabel lingkungan diatur dalam bentuk tepat yang diperlukan oleh program pemrosesan. Selain itu, jika nilai properti atau kunci Anda akan berisi tanda kutip tunggal, maka Anda perlu mengubah karakter pemisah bidang awk menjadi sesuatu yang Anda tahu tidak akan muncul, dan mengelilingi nilai dengan karakter itu. Misalnya, untuk digunakan %sebagai pemisah:

$ C__1="%my.key=the'value%"
$ set | awk -- 'BEGIN { FS="%" } /^C__/ {print $2}'
my.key=the'"'"'value

(output yang tepat akan tergantung pada shell Anda.) Anda harus mengambil langkah-langkah tambahan untuk memecahkan kode kutipan.

Groboclown
sumber