Dapatkah nama variabel shell menyertakan tanda hubung atau tanda hubung (-)?

38

Saya tidak dapat menggunakan -variabel dalam shell. Apakah ada cara untuk dapat menggunakannya, karena saya punya satu skrip yang tergantung pada variabel bernama:

$export a-b=c
-bash: export: `a-b=c': not a valid identifier

$export a_b=c

Pertama melempar kesalahan yang diberikan dan kedua bekerja dengan baik.

xyz
sumber
kemungkinan duplikat lintas situs: stackoverflow.com/questions/2821043/…
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件
Kerang biasanya tidak mengizinkan nama variabel tersebut. Anda harus melewati shell, mungkin bahkan dengan program C kustom memuat variabel ke lingkungan perintah Anda. Tidak bisakah Anda memperbaiki kesalahan ini (bahkan risiko keamanan yang mungkin terjadi)?
vonbrand

Jawaban:

47

Saya belum pernah bertemu shell Bourne-style yang diizinkan -dalam nama variabel. Hanya huruf ASCII (dari kedua kasus), _dan digit yang didukung, dan karakter pertama tidak boleh digit.

Jika Anda memiliki program yang memerlukan variabel lingkungan yang tidak cocok dengan pembatasan shell, jalankan dengan envprogram.

env 'strange-name=some value' myprogram

Perhatikan bahwa beberapa shell (mis. Dash modern , mksh, zsh) menghapus variabel yang namanya tidak mereka sukai dari lingkungan. ( Shellshock telah membuat orang lebih berhati-hati tentang nama-nama variabel lingkungan, sehingga pembatasan cenderung menjadi lebih ketat dari waktu ke waktu, tidak lebih permisif.) Jadi, jika Anda perlu meneruskan variabel yang namanya berisi karakter khusus untuk suatu program, berikan secara langsung, tanpa shell di antaranya ( env 'strange-name=some value' sh -c'…; myprogram'mungkin atau mungkin tidak berfungsi).

Gilles 'SANGAT berhenti menjadi jahat'
sumber
Tidak lagi berfungsi.
Jesse Glick
4
@ JesseGlick Ya, benar. (Komentar Anda akan berguna jika Anda mendefinisikan "tidak berfungsi": dengan data apa? Apa efeknya daripada efek yang diinginkan? Dan jika Anda mengatakan implementasi yang envAnda gunakan pada sistem operasi apa.)
Gilles 'SO-stop being evil '
Maaf. Ubuntu Yakkety dengan semua pembaruan, envdari coreutils, shdari dash: env 'with-dashes=value' bash -c 'env | fgrep dashes'berfungsi tetapi env 'with-dashes=value' sh -c 'env | fgrep dashes'tidak mencetak apa pun. Artinya, envitu sendiri baik-baik saja, tetapi Dash tampaknya secara khusus memblokir variabel-variabel ini. Jadi, jika program tersebut diluncurkan melalui pembungkus shell dengan #!/bin/shheader yang khas , tidak ada cara yang jelas untuk meneruskan variabel tersebut. Contoh solusi
Jesse Glick
@ JesseGlick Itu dasbor menghapus variabel. Anda harus menggunakan envlebih dekat ke situs panggilan program yang membutuhkan nama variabel ini, tanpa shell di antaranya. Dash tidak sendirian dalam menghapus variabel yang namanya tidak disukai.
Gilles 'SO- berhenti bersikap jahat'
1
@JesseGlick Memang benar bahwa beberapa hal yang digunakan untuk bekerja mungkin tidak lagi berfungsi, meskipun: sejak shellshock , orang-orang menjadi lebih konservatif tentang nama-nama variabel, dan dasbor memang berubah sejak saya menulis jawaban ini (bukan sebagai konsekuensi dari Shellshock, tetapi untuk menghindari bug di sepanjang baris yang sama). Saya telah menambahkan catatan untuk jawaban saya.
Gilles 'SO- berhenti menjadi jahat'
15

Itu tidak mungkin di Bash.

Dari bagian Definisi di halaman manual bash:

name Sebuah kata yang hanya terdiri dari karakter alfanumerik dan garis bawah, dan dimulai dengan karakter alfabet atau garis bawah. Disebut juga sebagai pengidentifikasi.

Dari bagian Parameter di halaman manual bash:

Parameter adalah entitas yang menyimpan nilai. Itu bisa berupa nama, angka, atau salah satu karakter khusus yang tercantum di bawah di bawah Parameter Khusus. Variabel adalah parameter yang dilambangkan dengan nama.

Lekensteyn
sumber
2
+1 untuk menunjukkan kegunaan halaman manual sekali lagi
ktf
2
Posting lama yang saya tahu, tetapi saya ingin menunjukkan bahwa halaman manual untuk pendatang baru bisa sangat samar. Saya masih memiliki waktu ketika saya perlu mencari penjelasan / contoh yang lebih baik. Siapa pun akan berbohong jika mereka mengatakan itu tidak pernah terjadi pada mereka.
TCZ8
1
@ TCZ8 Satu-satunya orang yang mengatakan kepada saya bahwa mereka menganggap halaman manual adalah 'samar' adalah jenis orang yang sama yang tidak membaca pesan kesalahan dan hanya membaca sekilas semuanya, melompati apa yang mereka perlu baca.
Miles Rout
13

Anda dapat mengakses variabel ditulis dgn tanda penghubung menggunakan referensi tidak langsung.

$ env 'my-hyphenated-variable=hello' /bin/bash
$ name='my-hyphenated-variable'
$ echo ${!name}
hello
Jon Nalley
sumber
1
Saya belum pernah mendengar fungsi ini sampai membaca komentar ini. Memberikan solusi yang jauh lebih mudah bagi saya daripada jawaban yang diterima.
DrStrangepork
7
Perilaku ini telah dinonaktifkan di versi bash yang lebih baru. Lihat stackoverflow.com/questions/36989263/… untuk analisis situasi secara menyeluruh.
Nicolas Dudebout
6

Jika skrip Anda bergantung pada nama variabel yang memiliki tanda hubung, itu adalah kesalahan pemrograman. Jika nyaman bagi Anda karena alat yang Anda gunakan secara teratur untuk membuat nama variabel berisi tanda hubung, Anda mungkin harus mempelajari lebih banyak dan alat yang berbeda.

Sudahkah Anda mencoba menggunakan tr untuk mengubah tanda hubung menjadi garis bawah?

hyphenated_name="a-b"
unhyphenated_name=$(echo $hyphenated_name | tr '-' '_')
declare -x $unhyphenated_name="some value"

Bash mengizinkan '-' muncul dalam nama fungsi. Saya melakukan ini sepanjang waktu. Sebagai contoh:

function foo-bar() {
   echo "$@"
}
Brian J. Fox
sumber
2

Karakter tanda hubung ( -) adalah karakter hentian dan tidak diizinkan sebagai bagian dari nama variabel. Ada beberapa cara untuk meretas ini dengan variabel yang dikutip, tetapi penguraiannya benar-benar bermasalah. Ada juga karakter lain dengan makna khusus dalam konteks nama variabel dalam bash, terutama tanda kurung, tanda kurung, karakter operator dan tanda kutip. (mis. {}()=+-&'"dan lebih banyak)

Saya menyarankan agar secara praktis Anda perlu menemukan paradigma lain untuk membangun skrip Anda. Anda mungkin memiliki gagasan hang over dari bahasa lain tentang "nama variabel variabel". Ini umumnya bukan ide yang baik dalam skrip shell.

Jika Anda mengedit ini atau mengajukan pertanyaan baru dengan detail konteks Anda dan apa yang ingin Anda capai, kami mungkin dapat menyarankan cara yang baik untuk membuat skrip.

Caleb
sumber
2

Manual Bash mendefinisikan "nama" sebagai:

Sebuah 'kata' yang hanya terdiri dari huruf, angka, dan garis bawah, dan dimulai dengan huruf atau garis bawah. 'Nama digunakan sebagai variabel shell dan nama fungsi. Juga disebut sebagai 'pengidentifikasi'.

Jadi, Anda tidak dapat menggunakan tanda hubung dalam nama.

Michael Hoffman
sumber
0

Kebanyakan shell hanya mendukung az, AZ, 0-9 dan _ untuk variablenames. Baca item kedua di halaman ini .


sumber
0

Anda dapat bermain dengan env dan sed.

Sebagai contoh, saya perlu membaca variabel ini 'ELASTICSEARCH_CLUSTER-NODES'.
Perintah env menampilkan ini:

~ $ env
ELASTICSEARCH_CLUSTER-NODES=elasticsearch:9200
JAVA_ALPINE_VERSION=8.212.04-r0
HOSTNAME=17eb9e7fec4c
...

Jadi untuk mengekstrak variabel:

ESHOST=`env | sed -n 's/ELASTICSEARCH_CLUSTER-NODES=\(.*\)/\1/p'`
Guillaume Paramelle
sumber
-1

Saya percaya bahwa hanya huruf, angka, dan garis bawah yang diizinkan untuk variabel bash. Ini adalah kasus di banyak bahasa pemrograman (javascript menjadi pengecualian).

Saya sarankan agar skrip Anda tidak bergantung pada jenis nama variabel tersebut.

Bahkan, Anda harus mencoba memprogram sedemikian rupa sehingga Anda dapat mengganti nama variabel dengan nama lain dan itu tidak membuat perbedaan. Secara umum, nama variabel harus menjelaskan apa yang berisi variabel. Ini membuatnya lebih mudah untuk di-debug; jika bukan untuk Anda, maka untuk pengembang berikutnya yang mencoba mencari tahu kodenya.


sumber
-1

Anda dapat menggunakan env perintah untuk mengatur dan menghapus variabel lingkungan dengan hiphens "-".

Untuk membuat Anda harus menggunakan env untuk menjalankan perintah Anda: env command. Anda melewati variabel dengan cara ini:

env a-b=c command

Lihat itu bekerja dengan:

env a-b=c env

atau untuk membuatnya lebih jelas:

env a-b=c env|grep 'a-b'
neves
sumber