ในขณะที่ตัวแปรสภาพแวดล้อมสามารถมีชื่อใด ๆ (รวมถึงสตริงที่ว่างเปล่า) ที่ไม่มีเครื่องหมายเท่ากับหรือเป็นโมฆะ null เชลล์แผนที่ตัวแปรสภาพแวดล้อมกับตัวแปรเชลล์และในเชลล์ส่วนใหญ่ชื่อตัวแปรจะถูก จำกัด ตัวอักษรและตัวเลข ASCII และอักขระตัว_
แรกสามารถ ' เสื้อเป็นหลัก (ยกเว้นสำหรับพารามิเตอร์ตำแหน่งและคนพิเศษอื่น ๆ เช่น$*
, $-
, $@
, ... (ที่ไม่ได้แมปไปยังตัวแปรสภาพแวดล้อมที่สอดคล้องกัน)) นอกจากนี้โปรดทราบว่าตัวแปรบางตัวสงวนไว้ / พิเศษโดย / ถึงเชลล์
ข้อยกเว้น:
rc
เปลือกและอนุพันธ์ของมันเช่นes
และakanga
สนับสนุนชื่อใด ๆ ยกเว้นสตริงที่ว่างเปล่าและผู้ที่มีทั้งหมดตัวเลขหรือมี=
ตัวละคร (และมักจะส่งออกตัวแปรทั้งหมดของพวกเขาที่มีต่อสิ่งแวดล้อมและระวังของตัวแปรพิเศษชอบ*
, status
, pid
... ):
; '%$£"' = test
; echo $'%$£"'
test
; '' = x
zero-length variable name
;
อย่างไรก็ตามมันใช้การเข้ารหัสของตัวเองสำหรับตัวแปรที่ชื่อไม่ได้มี alnums หรืออาร์เรย์เมื่อส่งผ่านในสภาพแวดล้อมของคำสั่งที่ถูกดำเนินการ:
$ 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
และzsh
(ยังbash
แต่สำหรับตัวอักษรเดียวไบต์) alnums สนับสนุนในสถานที่ปัจจุบันไม่เพียง แต่คน ASCII
$ Stéphane=1
$ echo "$Stéphane"
1
ในเปลือกหอยที่คุณสามารถเปลี่ยนสถานที่จะต้องพิจารณาตัวละครมากที่สุดเช่นอัลฟา แต่ยังคงที่จะไม่ทำงานสำหรับอักขระ ASCII .
เช่น คุณสามารถหลอกzsh
หรือksh
คิดว่า£
เป็นตัวอักษร แต่ไม่ใช่.
หรือตัวอักษร ASCII อื่น ๆ (ซึ่งการอนุญาตให้ใช้ตัวอักษรในชื่อตัวแปรเกี่ยวข้องไม่ใช่สำหรับกลุ่ม[[:alpha:]]
ตัวอย่าง)
ksh93
มีตัวแปรพิเศษที่ชื่อมีจุดคล้าย${.sh.version}
แต่ไม่มีการจับคู่กับตัวแปรสภาพแวดล้อมและเป็นพิเศษ .
คือการทำให้แน่ใจว่ามันไม่ได้มีความขัดแย้งกับตัวแปรอื่น ๆ ถ้ามันเลือกที่จะเรียกมันว่า$sh_version
แล้วมันจะได้สคริปต์เสียที่อาจเกิดขึ้นที่ใช้ตัวแปรที่แล้ว (ดูตัวอย่างวิธีการที่zsh
มีปัญหาเกี่ยวกับมัน$path
หรือ$commands
ตัวแปรอาร์เรย์ / กัญชาพิเศษ (ก csh ลา) ที่ทำลายบางสคริปต์)
หมายเหตุว่านอกเหนือไปจากเปลือกหอยไม่สนับสนุนตัวแปรเหล่านั้นหอยบางอย่างเช่น 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 %%%
%%%
เพื่อสรุปผลดีที่สุดคือการยึดติดอยู่กับชื่อตัวแปรการสนับสนุนจากเปลือกหอยมากที่สุดและได้พยายามที่จะใช้กรณีที่บนสำหรับตัวแปรสภาพแวดล้อม (และกรณีที่ต่ำกว่าหรือกรณีผสมสำหรับตัวแปรเปลือกไม่ส่งออก) การหลีกเลี่ยงผู้ที่มีความพิเศษในเปลือกหอย (เช่นIFS
, PS1
, BASH_VERSION
... )
หากคุณต้องการตั้งค่าตัวแปรดังกล่าวในเชลล์ที่ไม่สนับสนุน แต่ไม่ทิ้งคุณสามารถดำเนินการทดสอบด้วยตัวเองได้โดยใช้วิธีต่อไปนี้:
#! /bin/ksh -
perl -e 'exit 1 unless defined($ENV{"a.b"})' || exec env a.b=%%% "$0" "$@"
(เห็นได้ชัดว่าถ้าคุณจำเป็นต้องทำมันในช่วงกลางของสคริปต์นั่นไม่ได้ช่วยอะไร แต่คุณสามารถดูวิธีการนั้นเพื่อบันทึกและกู้คืนสภาพแวดล้อมการประมวลผลเชลล์ผ่านการประมวลผลซ้ำ) หรือลองใช้วิธีการดีบักเกอร์:
gdb --batch-silent -ex 'call putenv("a.b=%%%")' --pid="$$"
(ที่หนึ่งดูเหมือนว่าจะทำงานร่วมกับzsh
, yash
, csh
และtcsh
บน Linux amd64 แต่ไม่ได้มีการใด ๆ ของเปลือกหอยอื่น ๆ ที่ฉันพยายาม ( mksh
, ksh93
, bash
, dash
))