ฉันสามารถเรียกใช้ENV_VAR=value commandเพื่อให้ทำงานที่มีค่าเฉพาะสำหรับcommand ENV_VARอะไรที่เทียบเท่ากับ unset ENV_VARสำหรับcommand?
cmdสำหรับการที่
                ฉันสามารถเรียกใช้ENV_VAR=value commandเพื่อให้ทำงานที่มีค่าเฉพาะสำหรับcommand ENV_VARอะไรที่เทียบเท่ากับ unset ENV_VARสำหรับcommand?
cmdสำหรับการที่
                คำตอบ:
นอกเหนือจาก-iตัวเลือกซึ่งใช้envล้างสภาพแวดล้อมทั้งหมด POSIX ไม่มีวิธีการยกเลิกการตั้งค่าตัวแปร
อย่างไรก็ตามด้วยการenvใช้งานบางอย่าง(รวมถึง GNU, busybox'และ FreeBSD เป็นอย่างน้อย) คุณสามารถทำได้:
env -u ENV_VAR commandซึ่งจะทำงานในการลบทุกอินสแตนซ์ของENV_VARตัวแปรจากสภาพแวดล้อม (โปรดทราบว่ามันไม่ทำงานสำหรับตัวแปรสภาพแวดล้อมที่มีชื่อว่างเปล่า ( env -u ''อาจให้ข้อผิดพลาดหรือไม่มีประสิทธิภาพขึ้นอยู่กับการนำไปใช้แม้ว่าจะยอมรับทั้งหมดenv '=value'อาจเป็นข้อ จำกัด ที่เกิดขึ้นจากunsetenv()ฟังก์ชั่น C ซึ่ง POSIX ต้องการส่งคืนข้อผิดพลาดสำหรับสตริงว่างขณะที่ไม่มีข้อ จำกัด ดังกล่าวputenv()))
พกพาได้ (ใน POSIX shells) คุณสามารถทำสิ่งต่อไปนี้
(unset -v ENV_VAR; exec command)(โปรดทราบว่าในบางเชลล์การใช้execสามารถเปลี่ยนสิ่งที่commandรันได้: รันหนึ่งในระบบไฟล์แทนฟังก์ชั่นหรือ builtin เช่น (และจะหลีกเลี่ยงaliasการขยายตัวที่เห็นได้ชัด) เช่นenvด้านบนคุณต้องการละเว้นในกรณีเหล่านี้) .
แต่นั่นจะไม่ทำงานสำหรับตัวแปรสภาพแวดล้อมที่มีชื่อที่ไม่สามารถแมปกับตัวแปรเชลล์ได้ (โปรดทราบว่าบางเชลล์ที่ชอบmkshจะตัดตัวแปรเหล่านั้นออกจากสภาพแวดล้อมเมื่อเริ่มต้นอย่างไรก็ตาม) หรือตัวแปรที่ทำเครื่องหมายว่าเป็นแบบอ่านอย่างเดียว
-vใช้สำหรับเชลล์เป้าหมายและbashผู้ที่unsetไม่-vสามารถยกเลิกการตั้งค่าENV_VAR ฟังก์ชั่นหากไม่มีตัวแปรตามชื่อนั้น เชลล์อื่น ๆ ส่วนใหญ่จะไม่ตั้งค่าฟังก์ชั่นจนกว่าคุณจะผ่าน-fตัวเลือก (ไม่น่าจะสร้างความแตกต่างในทางปฏิบัติ)
(นอกจากนี้ระวังข้อผิดพลาด / misfeature ของbash/ mksh/ yashซึ่งunsetภายใต้สถานการณ์บางอย่างอาจไม่ล้างค่าตัวแปร แต่เปิดเผยตัวแปรในขอบเขตด้านนอก )
ถ้าperlมีคุณสามารถทำได้:
perl -e 'delete $ENV{shift@ARGV}; exec @ARGV or die$!' ENV_VAR commandซึ่งจะทำงานได้แม้กับตัวแปรสภาพแวดล้อมที่มีชื่อว่าง
ตอนนี้สิ่งเหล่านั้นจะไม่ทำงานหากคุณต้องการเปลี่ยนตัวแปรสภาพแวดล้อมสำหรับ builtin หรือฟังก์ชั่นและไม่ต้องการให้พวกเขาทำงานใน subshell เช่นในbash:
env -u LANG printf -v var %.3f 1.2 # would run /usr/bin/printf instead
(unset -v LANG; printf -v var %.3f 1.2) # changes to $var lost afterwards
(ที่นี่ unsetting LANG เป็นวิธีการที่ผิดที่ทำให้แน่ใจว่า.จะใช้และเข้าใจเป็นตัวคั่นทศนิยม. มันจะดีกว่าที่จะใช้LC_ALL=C printf...สำหรับที่)
ด้วยเชลล์บางตัวคุณสามารถสร้างขอบเขตโลคัลสำหรับตัวแปรโดยใช้ฟังก์ชัน:
without() {
  local "$1" # $1 variable declared as initially unset in bash¹
  shift
  "$@"
}
without LANG printf -v var %.3f 1.2
ด้วยzsh, คุณยังสามารถใช้ฟังก์ชันที่ไม่ระบุชื่อ:
(){local ENV_VAR; command}วิธีการนั้นจะไม่ทำงานในเชลล์บางตัว (เช่นเดียวกับที่ใช้เชลล์ Almquist) ซึ่งlocalไม่ได้ประกาศตัวแปรว่าเริ่มแรกแล้ว (แต่สืบทอดค่าและคุณสมบัติ) ในสิ่งเหล่านั้นคุณสามารถทำได้local ENV_VAR; unset ENV_VARแต่อย่าทำอย่างนั้นในmkshหรือyash( typesetแทนที่จะlocalเป็นแบบนั้น) เพราะวิธีนี้ใช้ไม่ได้ผลunsetจะเป็นการยกเลิกlocalเท่านั้น
¹ระวังด้วยว่าในbashนั้นโลคัลENV_VAR(แม้ว่าจะไม่ได้ตั้งค่า) จะเก็บแอตทริบิวต์ส่งออกไว้ ดังนั้นถ้าcommandเป็นฟังก์ชันที่กำหนดค่าให้ENV_VARตัวแปรจะพร้อมใช้งานในสภาพแวดล้อมของคำสั่งที่เรียกว่าหลังจากนั้น unset ENV_VARจะล้างแอตทริบิวต์นั้น หรือคุณสามารถใช้local +x ENV_VARซึ่งจะให้แน่ใจว่ากระดานชนวนสะอาด (ยกเว้นว่าตัวแปรที่ได้รับการประกาศให้อ่านอย่างเดียว แต่แล้วไม่มีอะไรที่คุณสามารถทำได้เกี่ยวกับมันbash)
env '=foo' python -c 'import os; print os.environ[""]'ลองยกตัวอย่างเช่น ฉันไม่คาดหวังว่าหลายคนจะต้องการตั้งค่าตัวแปรแบบนั้น
                    ไม่มีอะไรเทียบเท่าโดยตรงเท่าที่ฉันรู้ คุณสามารถใช้เชลล์ย่อย:
(unset ENV_VAR; exec command)(unset ENV_VAR; exec somecommand)ถ้าคุณต้องการที่จะเทียบเท่ากับต้นฉบับในประสิทธิภาพ (โดยการบริโภค subshell) ตามที่เป็นอยู่นี้จะเพิ่มทางแยกพิเศษ
                    commandเป็นคำสั่งสุดท้ายในการเรียกใช้ subshell
                    env -uเปลี่ยนแปลงสภาพแวดล้อมเปลือกสำหรับหนึ่งซับแทนการจดจำว่ามันเป็น
                    คุณสามารถใช้ได้ ENV_VAR= command
นี่ไม่ได้ทำการยกเลิกการตั้งค่าตัวแปร แต่อาจมีประโยชน์ในหลายกรณี (โดยปกติเชลล์สคริปต์จะใช้test -nเพื่อตรวจสอบว่ามีการตั้งค่าตัวแปร) หรือไม่:
$ export ENV_VAR=foo
$ mycommand
ENV_VAR: foo
$ ENV_VAR=bar mycommand
ENV_VAR: bar
$ ENV_VAR= mycommand
ENV_VAR: 
commandเป็นทางเลือกที่โชคร้ายของตัวยึดเนื่องจากมีจริงคือในตัวคำสั่งโดยใช้ชื่อที่mycommandหรือsomecommandอาจจะเป็นนิสัยที่ดีกว่าในการเข้ามา