เหตุใดฉันจึงไม่สามารถใช้ตัวแปรเป็นคำนำหน้าให้กับคำสั่งเพื่อตั้งค่าตัวแปรสภาพแวดล้อมได้


11

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

hello=hi bash -c 'echo $hello'

ฉันรู้ด้วยว่าเราสามารถใช้ตัวแปรเพื่อทดแทนส่วนใดส่วนหนึ่งของการเรียกใช้คำสั่งดังนี้:

$ cmd=bash
$ $cmd -c "echo hi" # equivalent to bash -c "echo hi"

ฉันประหลาดใจมากที่พบว่าคุณไม่สามารถใช้ตัวแปรเพื่อนำหน้าคำสั่งเพื่อตั้งค่าตัวแปรสภาพแวดล้อม กรณีทดสอบ:

$ prefix=hello=hi
$ echo $prefix # prints hello=hi
$ $prefix bash -c 'echo $hello'
hello=hi: command not found

เหตุใดฉันจึงไม่สามารถตั้งค่าตัวแปรสภาพแวดล้อมโดยใช้ตัวแปรได้ ส่วนนำหน้าเป็นส่วนพิเศษหรือไม่? ฉันสามารถทำให้มันทำงานได้โดยใช้ eval ข้างหน้า แต่ฉันก็ยังไม่เข้าใจว่าทำไม ฉันใช้ทุบตี 4.4


1
คุณสามารถใช้envแทนevalซึ่ง IIRC นั้นปลอดภัยกว่า แต่ช้ากว่า
wjandrea

คำตอบ:


14

ฉันสงสัยว่านี่เป็นส่วนหนึ่งของลำดับที่ดึงดูดคุณ:

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

มาจากคู่มืออ้างอิง Bashในส่วนของ Simple Command Expansion

ในตัวอย่างเช่นไม่มีตัวแปรสภาพแวดล้อมที่มีการตั้งค่าและทุบตีกระบวนการบรรทัดคำสั่งผ่านการขยายตัวพารามิเตอร์ออกcmd=bashbash -c "echo hi"

ในตัวอย่างเช่นมีการมอบหมายงานอีกครั้งไม่มีตัวแปรในครั้งแรกผ่านเพื่อให้การประมวลผลยังคงขยายตัวพารามิเตอร์ผลในคำแรกของprefix=hello=hihello=hi

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

ดูการประมวลผลและผลลัพธ์ของมันภายใต้set -x:

$ prefix=hello=hi
+ prefix=hello=hi
$ $prefix bash -c 'echo $hello'
+ hello=hi bash -c 'echo $hello'
-bash: hello=hi: command not found
$ hello=42 bash -c 'echo $hello'
+ hello=42
+ bash -c 'echo $hello'
42

สำหรับรูปแบบที่ปลอดภัยยิ่งขึ้นของ "ตัวแปรส่วนขยาย" - เป็น - "ตัวแปรสภาพแวดล้อม" มากกว่าevalให้พิจารณาข้อเสนอแนะของ wjandrea ของenv :

prefix=hello=hi
env "$prefix" bash -c 'echo "$hello"'
hi

มันไม่ได้เป็นการกำหนดตัวแปรบรรทัดคำสั่งอย่างเคร่งครัดเนื่องจากเราใช้envฟังก์ชันหลักของยูทิลิตี้ในการกำหนดตัวแปรสภาพแวดล้อมให้กับคำสั่ง แต่มันก็บรรลุเป้าหมายเดียวกัน $prefixตัวแปรจะขยายตัวระหว่างการประมวลผลของบรรทัดคำสั่งให้ชื่อ = มูลค่าให้กับผู้ที่ผ่านมันไปให้envbash


3
ในทำนองเดียวกัน$foo=bar bash -c ...จะไม่ทำงานเพราะ$foo=barไม่ใช่การกำหนดตัวแปร (ไม่ว่าจะเป็นค่าใด$foo) เพราะ$foo=barไม่เหมาะกับname=valueรูปแบบสำหรับการกำหนดตัวแปร
muru

3

เพราะ$prefixไม่ใช่งานที่มอบหมาย @ Jeff มีคำอธิบายอีกต่อไป

คุณสามารถทำสิ่งที่คล้ายกันด้วยฟังก์ชั่นแทน:

$ prefix() { hello=hi "$@"; }
$ prefix bash -c 'echo "$hello"'
hi

... และคุณยังสามารถเรียงซ้อนหากคุณต้องการ:

$ foo() { foo=123 "$@"; }
$ bar() { bar=456 "$@"; }
$ foo bar bash -c 'echo "$bar $foo"'
456 123
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.