如何導出其中包含點的變數。當我嘗試時,我得到“無效的變數名稱”:
export my.home=/tmp/someDir
-ksh: my.home=/tmp/someDir: invalid variable name
即使轉義元字元點 (.) 也無濟於事
$ export my\.home=/tmp/someDir
export: my.home=/tmp/someDir: is not an identifier
答案1
至少對於bash
手冊頁將導出語法定義為:
export [-fn] [name[=word]] ...
它還將“名稱”定義為:
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.
因此,您確實無法定義變量,my.home
因為它不是有效的標識符。
我非常確定您的 ksh 有一個非常相似的標識符定義,因此不允許這種變數。 (看看它的手冊頁。)
我也非常確定有某種通用標準(POSIX?)指定允許什麼作為識別符(因此也可以作為變數名稱)。
如果因為某些原因你確實需要這種變量,你可以使用類似的東西
env "my.home=/tmp/someDir" bash
無論如何都要定義它。但話又說回來,您將無法使用正常的 shell 語法存取它。在這種情況下,您可能需要另一種語言,例如 perl:
perl -e 'print $ENV{"my.home"}'
例如
env "my.home=/tmp/someDir" perl -le 'print $ENV{"my.home"}'
應該打印你的路徑。
答案2
雖然環境變數可以具有不包含等號或空字節的任何名稱(包括空字串),但 shell 將環境變數映射到 shell 變量,並且在大多數 shell 中,變數名稱僅限於 ASCII 字母數字字符,並且_
第一個字元可以是「 t 是一個數字(除了位置參數和其他特殊參數,如$*
、$-
、$@
、 …(未對應到對應的環境變數))。另請注意,有些變數是保留/特殊通過/到外殼。
例外情況:
shell
rc
及其衍生產品喜歡es
並akanga
支援除空字串之外的任何名稱,以及全數字或包含=
字元的名稱(並且始終將所有變數匯出到環境中,並注意特殊變量,例如*
,status
,pid
...):; '%$£"' = test ; echo $'%$£"' test ; '' = x zero-length variable name ;
但是,當在正在執行的命令環境中傳遞時,它對名稱不包含數字的變數或陣列使用自己的編碼:
$ 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
和(也yash
但僅適用於單字元)支援當前語言環境中的數字,而不僅僅是 ASCII 字元。zsh
bash
$ Stéphane=1 $ echo "$Stéphane" 1
在這些 shell 中,您可以更改區域設定以將大多數字元視為 alpha,但這仍然不適用於 ASCII 字符,例如
.
.您可以愚弄zsh
或ksh
認為£
它是一個字母,但不是那個字母.
或任何其他 ASCII 字元(在變數名稱中允許使用字元的情況下,[[:alpha:]]
例如對於 glob 而言)。ksh93
具有名稱包含點(如 )的特殊變量${.sh.version}
,但這些變數未對應到環境變數且是特殊的。這.
是為了確保它不與其他變數衝突。如果它選擇呼叫它$sh_version
,那麼它可能會破壞已經使用該變數的腳本(例如,請參閱zsh
它的問題$path
或$commands
特殊的陣列/散列變數(a la csh)如何破壞某些腳本)。
請注意,除了不支援這些變數的 shell 之外,某些 shell(如 pdksh/mksh)也支援消除將它們從接收到的環境中刪除(bash
刪除名稱為空的環境字串,ash
並ksh
刪除bash
那些不包含字元的環境字串=
):
$ 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 %%%
%%%
總而言之,最好是堅持使用大多數 shell 支援的變數名,甚至嘗試對環境變數使用大寫(對未導出的 shell 變數使用小寫或混合大小寫),避免使用 shell 中特殊的變數名(例如IFS
、PS1
、BASH_VERSION
. ..)。
如果您確實需要在不支援它們但不丟棄它們的 shell 中設定這樣的變量,您可以自行重新執行,例如:
#! /bin/ksh -
perl -e 'exit 1 unless defined($ENV{"a.b"})' || exec env a.b=%%% "$0" "$@"
(顯然,如果您需要在腳本中間執行此操作,那將無濟於事,但您可以看看那種方法透過重新執行保存和還原 shell 執行環境)。或嘗試調試器方法:
gdb --batch-silent -ex 'call putenv("a.b=%%%")' --pid="$$"
(這個似乎可以在 Linux amd64 上使用zsh
、yash
、csh
和tcsh
,但不能與我嘗試過的任何其他 shell 一起使用(mksh
、ksh93
、bash
、dash
))。
答案3
正如其他帖子指出的那樣,最常見的 shell 不允許設定名稱中帶有句點的環境變數。然而,我發現一些情況,特別是涉及 Docker 和調用的程式時,軟體需要帶有句點的鍵值。
但是,在每種情況下,這些鍵值對都可以透過環境變數以外的其他方式傳遞給程式。例如,在 Ant 中,您可以使用「-propertyfile(檔案名稱)」來傳入屬性檔案格式的鍵值集合。 Confd 允許「-backend file -file(yaml 檔案)」。
我以「C__any_value='my.property.key=the value'」的形式傳遞了環境變數。然後我切換程式調用以首先生成檔案:
set | awk -- 'BEGIN { FS="'\''" } /^C__/ {print $2}' > my-key-values.txt
在 Borne Shell 中,該set
命令將以以下形式在單獨的行上輸出每個屬性
C__any_value='my.property.key=the value'
此awk
命令將僅處理以 開頭的環境變量C__
,然後提取單引號中包含的值。
此方法要求以處理程序所需的精確形式設定環境變數值。此外,如果您的屬性值或鍵將包含單引號,那麼您需要將 awk 字段分隔符更改為您知道不會出現的字符,並用該字符將值括起來。例如,用作%
分隔符號:
$ C__1="%my.key=the'value%"
$ set | awk -- 'BEGIN { FS="%" } /^C__/ {print $2}'
my.key=the'"'"'value
(精確的輸出取決於您的 shell。)您將需要採取額外的步驟來解碼轉義的引號。
答案4
@michas 的答案非常正確,但可以將其擴展為export
使用點環境名稱來模擬函數。
若要「匯出」此類變量,您可以使用命令exec
在目前 shell 中env
。例如,要匯出test.env=foo
變量,請使用:
exec env "test.env=foo" $SHELL
Exec 將以新進程取代目前 shell,其中新進程將是目前 shell ( ) 的新實例,$SHELL
並帶有附加環境變數test.env
(由 新增env "test.env=foo"
)。因此,在執行此命令之後,您可以從進程中存取它,例如:
perl -e 'print $ENV{"test.env"}'