“ export var = value” ไม่สามารถใช้ได้ที่ไหน


31

ฉันหยิบขึ้นมา - อาจจะเป็น Usenet ในช่วงกลางปี ​​1990 (!) - สิ่งก่อสร้างนั้น

export var=value

เป็น Bashism และการแสดงออกแบบพกพาคือ

var=value
export var

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

Googling สำหรับ"export: command not found"ดูเหมือนจะไม่เกิดกรณีใด ๆ ที่ใครบางคนมีปัญหานี้จริง ๆ ดังนั้นแม้ว่ามันจะเป็นของแท้ แต่ฉันคิดว่ามันไม่ธรรมดา

(ความนิยมที่ฉันได้รับดูเหมือนว่าเป็นมือใหม่ที่คัดลอก / วางเครื่องหมายวรรคตอนและจบลงด้วย'export: command not foundหรือบางส่วนหรือพยายามใช้exportกับsudoและcshผู้ใช้มือใหม่ที่พยายามใช้ไวยากรณ์เชลล์เป้าหมาย)

แน่นอนฉันสามารถบอกได้ว่าการทำงานบน OS X และ Linux distros ต่าง ๆ รวมทั้งคนที่เป็นshdash

sh$ export var=value
sh$ echo "$var"
value
sh$ sh -c 'echo "$var"'  # see that it really is exported
value

ในโลกปัจจุบันมันปลอดภัยหรือไม่ที่จะบอกว่าexport var=valueปลอดภัยที่จะใช้?

ฉันต้องการที่จะเข้าใจว่าผลที่ตามมาคืออะไร ถ้ามันไม่สามารถพกพาไปยัง v7 "Bourne classic" ได้นั่นไม่ใช่เรื่องไร้สาระ หากมีระบบการผลิตที่เชลล์ไม่สามารถรับมือกับไวยากรณ์นี้ได้จริงนั่นจะเป็นประโยชน์ที่จะรู้


2
ขอบคุณในที่สุดฉันก็เข้าใจว่าทำไมฉันจึงเห็นบ่อยครั้งที่สิ่งที่ฉันคิดว่าไร้ประโยชน์: var = value; export var
Thorsten Staerk

2
ยังคงมีกล่องโซลาริสอยู่สองสามกล่องที่เตะไปรอบ ๆ และกล่องเหล่านั้นประหยัดในเครื่องมือมาตรฐานของพวกเขา อีกด้านหนึ่งของสเปกตรัมไม่ได้busyboxมาพร้อมกับกระสุนขนาดเล็กของมันเอง (ฉันไม่ได้อยู่ในฐานะที่จะลองในวินาทีนี้)
Ulrich Schwarz

ขอบคุณ Ulrich โซลาริสอาจเป็นสาเหตุของความผิดพลาดที่ว่าทำไมไวยากรณ์ที่ยาวนานนี้จึงยังคงอยู่
Thorsten Staerk

คำตอบ:


20
export foo=bar

ไม่ได้รับการสนับสนุนจาก Bourne shell (เชลล์เก่าจากยุค 70 ซึ่งshการใช้งานที่ทันสมัยเช่น ash / bash / ksh / yash / zsh สืบทอดมา) kshที่ได้รับการแนะนำให้รู้จักกับ

ในเชลล์เป้าหมายคุณจะทำ:

foo=bar export foo

หรือ:

foo=bar; export foo

หรือด้วยset -k:

export foo foo=bar

ตอนนี้พฤติกรรมของ:

export foo=bar

แตกต่างจากเปลือกหอย

ปัญหาคือการกำหนดและอาร์กิวเมนต์คำสั่งง่าย ๆ จะถูกแยกวิเคราะห์และตีความแตกต่างกัน

foo=barข้างต้นจะตีความโดยเปลือกบางเป็นอาร์กิวเมนต์คำสั่งและอื่น ๆ ตามที่ได้รับมอบหมาย (บางครั้ง)

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

a='b c'
export d=$a

ถูกตีความว่า:

'export' 'd=b' 'c'

ด้วยเชลล์บางตัว ( ash, เวอร์ชันที่เก่ากว่าzsh(ใน sh emulation), yash) และ:

'export' 'd=b c'

ในส่วนอื่น ๆ ( bash, ksh)

ในขณะที่

export \d=$a

หรือ

var=d
export $var=$a

จะตีความเหมือนกันในเชลล์ทั้งหมด (เป็น'export' 'd=b' 'c') เพราะเครื่องหมายแบ็กสแลชหรือเครื่องหมายดอลลาร์หยุดเชลล์เหล่านั้นที่สนับสนุนให้พิจารณาอาร์กิวเมนต์เหล่านั้นเป็นการกำหนด

หากexportมีการอ้างถึงตัวมันเองหรือผลของการขยายตัว (บางส่วน) ขึ้นอยู่กับเปลือกหอยมันก็จะหยุดรับการรักษาพิเศษ

ดูที่ " จำเป็นต้องใช้เครื่องหมายคำพูดสำหรับการกำหนดตัวแปรท้องถิ่นหรือไม่ " สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับเรื่องนั้น

แม้ว่าไวยากรณ์ของ Bourne:

d=$a; export d

ถูกตีความแบบเดียวกันโดยเชลล์ทั้งหมดโดยไม่มีความกำกวม ( d=$a export dจะทำงานในเชลล์เป้าหมายและเชลล์ที่สอดคล้องกับ POSIX แต่ไม่ได้อยู่ในเวอร์ชันล่าสุดzshยกเว้นในการshจำลอง)

มันแย่กว่านั้นมาก ดูตัวอย่างที่การอภิปรายล่าสุดเกี่ยวกับbashเวลาที่เกี่ยวข้องกับอาร์เรย์

(IMO มันเป็นความผิดพลาดที่จะแนะนำคุณสมบัตินั้น)


ฉันรู้สึกประหลาดใจที่ไม่จำเป็นต้องใช้เครื่องหมายอัฒภาคfoo=bar export fooเนื่องจากฉันเห็นมาตลอดแล้ว ฉันรู้ว่าการส่งออกในตัว แต่ทำไมfoo=bar; foo=baz export foo; echo $fooทำงานแตกต่างกันกว่าfoo=bar; foo=baz /bin/cat /dev/null; echo $foo?
jrw32982 รองรับโมนิก้า

3
@ jrw32982 เพราะมันเป็นแบบบิลท์อิน คุณยังคงได้รับใน POSIX shells แต่เฉพาะสำหรับbuildins พิเศษซึ่งexportก็คือ
Stéphane Chazelas เมื่อ

แม้ว่ามันจะกล่าวถึงdeclareไม่ได้exportผมขอแนะนำให้ทุกคนที่ที่ใส่ใจเกี่ยวกับการรักษาความปลอดภัยอ่านการอภิปรายที่ลิงค์ที่ให้ไว้กับStéphaneChazelas bash.bugs
John1024

คำตอบที่ดี! แต่มันใช้เวลานานกว่าที่จะได้รับการd=$a export dตีความเหมือนกันโดยกระสุนทั้งหมดโดยไม่มีความคลุมเครือ ;-)
conny

@conny d=$a export dไม่ทำงานอีกต่อไปzshดังนั้นฉันได้อัปเดตคำตอบแล้ว ดูการแก้ไข
Stéphane Chazelas

28

มันไม่ใช่ bashism แต่เป็นไวยากรณ์ที่สอดคล้องกับ POSIX อันที่จริงมันเริ่มเป็น kshism เมื่อนานมาแล้วและต่อมาถูกนำมาใช้โดยเชลล์ที่ใช้ไวยากรณ์บอร์นเกือบทั้งหมด ข้อยกเว้นที่ฉาวโฉ่เพียงข้อเดียวคือ/bin/shใน Solaris 10 และเก่ากว่าซึ่งยึดติดกับไวยากรณ์เชลล์ Bourne ดั้งเดิม หวังว่า Solaris 11 ใช้ POSIX /bin/shเปลือกสอดคล้องเป็น

โดยวิธีการexportแล้วเป็นคำสั่งในตัวในเปลือกบอร์นมรดกเพื่อ googling สำหรับexport: command not foundถูกทำให้เข้าใจผิด

นี่คือพฤติกรรมของบอร์นเชลล์แบบดั้งเดิมเมื่อexportรวมเข้ากับผลกระทบ:

$ export var=22
var=22: is not an identifier

สำหรับความคิดถึงนั้นซอร์สโค้ดของเชลล์เป้าหมายเดิมนี้สามารถใช้งานได้และสามารถรวบรวมได้สำหรับ Unix และ Linux ส่วนใหญ่


ขอบคุณมากสำหรับข้อมูลเชิงลึกที่ผ่านมาและข้อความแสดงข้อผิดพลาดที่ถูกต้องถึง google สำหรับ! เห็นได้ชัดในการหวนกลับบลัชออ ...
tripleee

4
นี่ไม่ใช่ซอร์สโค้ดของเชลล์เป้าหมายเดิมนั่นคือ OpenSolaris sh ที่ได้รับการแก้ไข มันคือเปลือก Bourne แต่หลังจากผ่านการวิวัฒนาการมาหลายทศวรรษ เปลือก Bourne ดั้งเดิมที่ถูกส่งมาพร้อมกับ Unix V7 สามารถพบได้ที่ Unix Heritage Society
Stéphane Chazelas

1
@ StéphaneChazelasพูดอย่างเคร่งครัดคุณพูดถูกปกติ โปรดทราบว่าฉันไม่ได้เขียน "Bourne shell ดั้งเดิม" แต่ "Bourne shell ดั้งเดิม" เนื่องจากฉันอ้างถึงเชลล์ที่ใช้โดย Solaris 10 และซอร์สโค้ดที่สามารถคอมไพล์บนแพลตฟอร์มที่ทันสมัย โปรดทราบว่า Bourne shell มีคุณสมบัติหลายอย่างที่เพิ่มระหว่างปี 1977 และ 1989 แต่จากนั้นก็หยุดที่จะพัฒนา (นอกพอร์ต / ปรับให้เข้ากับแพลตฟอร์มที่ใหม่กว่าและแก้ไขข้อผิดพลาด) ในช่วง 25 ปีที่ผ่านมา
jlliagre
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.