/ bin / sh แหล่งที่มาจาก stdin (จากโปรแกรมอื่น) ไม่ใช่ไฟล์


14

เป็นคนที่ค่อนข้างยุ่งยากในการตั้งชื่อ ...

โดยทั่วไปฉันมีโปรแกรมที่เมื่อรัน print บน STDOUT ชุดของตัวแปร shell:

$ ./settings
SETTING_ONE="this is setting one"
SETTING_TWO="This is the second setting"
ANOTHER_SETTING="This is another setting".

ผมต้องการที่จะทำงานนี้จากภายในสคริปต์เปลือกเป็นถ้า STDOUT sourceถูกประเมินด้วย

ฉันต้องการทำบางสิ่งเช่น ...

source `./settings`

... แต่แน่นอนว่าไม่ได้ผล

ฉันรู้ว่าฉันสามารถทำได้:

./settings >/tmp/file
source /tmp/file

แต่ฉันไม่ต้องการทำอย่างนั้นจริงๆ

เบาะแสใด ๆ

คำตอบ:


16

คุณสามารถใช้eval:

eval "$(./settings)"

eval "`./settings`"

ขออภัยควรพูดถึงมัน / bin / sh ไม่ได้ทุบตี $ () ไม่ทำงาน ฉันได้อัปเดตคำถามแล้ว
Majenko

@ แมท: เอ่อ sh ถูกทุบตีในระบบส่วนใหญ่ เว้นแต่คุณจะหมายถึง Ubuntu รุ่นล่าสุดซึ่งมันถูกแทนที่ด้วยเส้นประ
Hello71

@ Matt: ในกรณีนั้น backticks ควรทำงาน แต่คุณควรเพิ่มรุ่นที่แน่นอนshด้วยเช่นกันมันอาจเป็น symlink สำหรับ dash, ash, busybox ... ฉันไม่เห็นสำเนา "the 'sh'" live จริง
user1686

1
@ Matt: ดังนั้นคุณมี ... ระบบที่น่าสนใจที่นั่น โดยเฉพาะอย่างยิ่งเนื่องจากการสนับสนุนรูปแบบ "sh" เกือบทั้งหมด$( )- เริ่มต้นด้วยเชลล์ของ Almquist ใน4.3BSD - และเป็น POSIX ด้วย (หมายเหตุ: ไม่ใช่การโต้เถียงเพียงแค่อยากรู้อยากเห็น)
user1686

$ () มีอยู่แล้วมันไม่ทำงานอย่างนั้นในกรณีนี้ FreeBSD 8.2's / bin / sh
Majenko

15

บนระบบที่/dev/fdพร้อมใช้งาน bash สนับสนุนการทดแทนกระบวนการ:

source <(./settings)

ที่นี่<( )จะขยายไปยังเส้นทางที่กำหนดโดยอัตโนมัติภายใต้/dev/fd/...ซึ่ง./settingsสามารถส่งออกของ


1
ในคู่มือทุบตีนี้เรียกว่า "การทดแทนกระบวนการ"
เกล็นแจ็คแมน

6
declare `./settings`

หรือแน่นอน ...

export `./settings`

ทดสอบมันแน่นอน ...

export `echo -e "asdf=test\nqwerty=dvorak"` ; echo $asdf $qwerty

การจัดการช่องว่าง:

eval export `./settings`

อ๊ะexportเคล็ดลับใช้งานได้! ขอบคุณ
Majenko

ตอนนี้ - ฉันจะจัดการช่องว่างด้วยค่าได้อย่างไร
Majenko

@ Matt: ฉันไม่สามารถใช้ backticks ในความคิดเห็นได้ดังนั้นโปรดดูคำตอบที่แก้ไขแล้ว
user1686

@grawity: ใช่คุณสามารถ ...a backtick --> ` <-- and here's another one --> ` <--
Hello71

2

source /dev/stdin < ./settings

ฉันคิดว่า / dev / stdin เป็นเพียง Linux เท่านั้น


ที่พยายามหาแหล่งเนื้อหาของการตั้งค่า แม้จะมี './settings' ก็ล้มเหลวด้วย './settings': คลุมเครือ ('= backtick)
Majenko

/dev/stdinใช้ได้กับ BSD และ Cygwin ด้วย
user1686

1
|อย่างไรก็ตามการใช้งานจะไม่ทำงาน (อย่างน้อยก็ไม่แน่นอน) เพราะทั้งสองด้านของไพพ์เป็นกระบวนการย่อยแยกดังนั้นคำสั่งที่มาจะไม่ส่งผลกระทบต่อเชลล์ปัจจุบัน
user1686

1
แก้ไขเพื่อสะท้อนว่า
LawrenceC

1
ฉันชอบ/dev/stdinเคล็ดลับนี้แต่สิ่งที่คำตอบของคุณทำจริง ๆ แล้วเทียบเท่ากับที่ราบsource ./settingsโดยไม่ต้องดำเนินการ เราสามารถใช้เอกสารที่นี่เพื่อเอาชนะสิ่งนี้: source /dev/stdin <<EOF \n $(./settings) \n EOF.
tlwhitec

0

ต้องการให้มุมมองอื่นที่นี่เป็นคำตอบอื่น ๆ สร้างไฟล์และไม่ดึงโดยตรงจาก stdin ฉันมีงานสร้างบางอย่างที่จำเป็นต้องส่งข้อมูลสภาพแวดล้อมที่เตรียมไว้ไปยังสคริปต์หลายตัว สิ่งที่ฉันกำลังทำคือการเตรียมการกำหนดตัวแปรที่เข้ากันได้กับ Bash ในสตริง:

Var1="Foo"
Var2="Bar"
Var3="Baz"

เมื่อฉันเตรียมที่จะรันสคริปต์ฉัน base64 เข้ารหัสสตริงหลายบรรทัดด้านบนและไพพ์ลงในเชลล์สคริปต์ของฉัน:

echo base64EncodedParameters | build.sh

ใน build.sh ฉันอ่านจาก stdin, base64 ถอดรหัสและประเมินผลลัพธ์

params=""
while read line; do params="${params}${line}"; done
eval `echo $params | base64 -D`

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