การส่งออกตัวแปรที่มีจุด (.) อยู่ในนั้น


38

วิธีการส่งออกตัวแปรที่มีจุดอยู่ในนั้น ฉันได้รับ 'ชื่อตัวแปรที่ไม่ถูกต้อง' เมื่อพยายาม:

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

แม้แต่การหลบหนี metacharacter dot (.) ก็ไม่ได้ช่วยเช่นกัน

$ export my\.home=/tmp/someDir
export: my.home=/tmp/someDir: is not an identifier


1
โชคไม่ดีที่มันไม่ปรากฏเมื่อฉันพิมพ์ / ค้นหาคำถามที่คล้ายกัน ขอโทษ ..
user1587504

คำตอบ:


49

อย่างน้อยสำหรับbashman page จะกำหนดไวยากรณ์เอ็กซ์ปอร์ตเป็น:

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

เพื่อกำหนดมันต่อไป แต่จากนั้นอีกครั้งคุณจะไม่สามารถเข้าถึงได้โดยใช้ไวยากรณ์เชลล์ปกติ ในกรณีนี้คุณอาจต้องการภาษาอื่นเช่น Perl:

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

ตัวอย่างเช่น

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

ควรพิมพ์เส้นทางของคุณ


มันเป็นเพราะในการรวมของมด และน่าเสียดายที่มันไม่อนุญาตให้ตั้ง / ส่งออกตัวแปรจากยูนิกซ์ ยอมรับคำตอบของคุณ ..
user1587504

1
โดยปกติแล้วมดจะถูกกำหนดค่าโดยตัวแปรสภาพแวดล้อมเดียวที่เรียกว่าANT_OPTSหรือโดย ~ / .antrc ไม่จำเป็นต้องใช้ชื่อตัวแปรสภาพแวดล้อมแปลก ๆ สำหรับมดเอง
michas

8

ในขณะที่ตัวแปรสภาพแวดล้อมสามารถมีชื่อใด ๆ (รวมถึงสตริงที่ว่างเปล่า) ที่ไม่มีเครื่องหมายเท่ากับหรือเป็นโมฆะ 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))


1
mksh(และpdksh) สร้างกระบวนการสภาพแวดล้อมที่พวกเขาวางไข่ได้อย่างสมบูรณ์ตั้งแต่เริ่มต้นโดยใช้เฉพาะพารามิเตอร์เหล่านั้นที่ส่งออกในสภาพแวดล้อมการดำเนินการเชลล์ปัจจุบันดังนั้นจึงไม่มีวิธีที่จะส่งผ่านตัวแปรเหล่านั้นผ่านเชลล์เหล่านั้น (หมายเหตุว่าตัวแปรที่จะส่งผ่านไปอาจมีการเปลี่ยนแปลงเช่นฉันวางแผนที่จะสนับสนุนการส่งออกอาร์เรย์สำหรับmkshบางวัน.)
mirabilos

0

ดังที่โพสต์อื่น ๆ ชี้ให้เห็นเชลล์ทั่วไปส่วนใหญ่ไม่อนุญาตให้ตั้งค่าตัวแปรสภาพแวดล้อมด้วยจุดในชื่อ อย่างไรก็ตามฉันได้พบสถานการณ์โดยเฉพาะอย่างยิ่งที่เกี่ยวข้องกับนักเทียบท่าและโปรแกรมที่เรียกใช้โดยที่ซอฟต์แวร์ต้องการค่าคีย์ที่มีจุด

อย่างไรก็ตามในแต่ละสถานการณ์เหล่านี้คู่คีย์ - ค่าสามารถส่งผ่านไปยังโปรแกรมผ่านวิธีการอื่นนอกเหนือจากตัวแปรสภาพแวดล้อมเพียงอย่างเดียว ตัวอย่างเช่นใน Ant คุณสามารถใช้ "-propertyfile (filename)" เพื่อส่งผ่านคอลเลกชันที่จัดรูปแบบไฟล์คุณสมบัติของคีย์ - ค่า Confd อนุญาตสำหรับ "-backend file -file (ไฟล์ yaml)"

ฉันผ่านตัวแปรสภาพแวดล้อมในรูปแบบ "C__any_value = 'my.property.key = ค่า'" จากนั้นฉันเปลี่ยนการเรียกใช้โปรแกรมเป็นครั้งแรกเพื่อสร้างไฟล์:

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

setคำสั่งใน Borne เชลล์ออกจะสถานที่ให้บริการในแต่ละบรรทัดที่แยกต่างหากในรูปแบบ

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

(เอาต์พุตที่แม่นยำจะขึ้นอยู่กับเชลล์ของคุณ) คุณจะต้องดำเนินการขั้นตอนพิเศษเพื่อถอดรหัสการอ้างอิงคำพูด

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.