/ bin / sh nguồn từ stdin (từ chương trình khác) không tập tin


14

Một loại khó khăn để đặt tên này ...

Về cơ bản tôi có một chương trình mà khi chạy in trên STDOUT một tập hợp các biến shell:

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

Tôi muốn chạy cái này từ trong tập lệnh shell như thể STDOUT đang được đánh giá source.

Tôi muốn làm một cái gì đó như ...

source `./settings`

... nhưng tất nhiên là không được.

Tôi biết tôi có thể làm:

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

nhưng tôi thực sự không muốn làm điều đó

Bất kì manh mối nào?

Câu trả lời:


16

Bạn có thể sử dụng eval:

eval "$(./settings)"

eval "`./settings`"

Xin lỗi, nên đã đề cập, đó là / bin / sh không bash. $ () không hoạt động. Tôi đã cập nhật câu hỏi.
Majenko

@Matt: Chà, sh là bash trên hầu hết các hệ thống. Tất nhiên trừ khi bạn có nghĩa là các phiên bản Ubuntu gần đây, nơi nó đã được thay thế bằng dấu gạch ngang.
Hello71

@Matt: Trong trường hợp đó, backticks nên hoạt động. Nhưng bạn cũng nên thêm phiên bản chính xác của shnó - đó có thể là một liên kết tượng trưng cho dấu gạch ngang, tro, busybox ... Tôi chưa thấy một bản sao của "sh 'thực" trực tiếp.
dùng1686

1
@Matt: Vậy là bạn đã có một ... hệ thống thú vị đấy. Đặc biệt là vì hầu hết tất cả các hỗ trợ biến thể "sh" $( )- bắt đầu với lớp vỏ của Almquist trong 4.3BSD - và đó cũng là POSIX. (Lưu ý: không tranh cãi, chỉ tò mò.)
user1686

$ () tồn tại, nó chỉ không hoạt động như thế trong trường hợp này. FreeBSD 8.2's / bin / sh
Majenko

15

Trên các hệ thống /dev/fdcó sẵn, bash hỗ trợ thay thế quy trình:

source <(./settings)

Ở đây, <( )sẽ mở rộng thành một đường dẫn được gán tự động, theo /dev/fd/...đó đầu ra của ./settingscó thể được đọc.


1
Trong hướng dẫn bash, điều này được gọi là "thay thế quá trình".
glenn jackman

6
declare `./settings`

Hoặc tất nhiên ...

export `./settings`

Kiểm tra nó tất nhiên ...

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

Xử lý khoảng trắng:

eval export `./settings`

Aha, exportthủ thuật hoạt động! Cảm ơn
Majenko

Bây giờ - làm thế nào tôi có thể xử lý khoảng trắng trong một giá trị?
Majenko

@Matt: Tôi không thể sử dụng backticks trong các bình luận, vì vậy vui lòng xem câu trả lời được chỉnh sửa.
dùng1686

@grawity: Có, bạn có thể ...a backtick --> ` <-- and here's another one --> ` <--
Hello71

2

source /dev/stdin < ./settings

Tôi nghĩ / dev / stdin chỉ là một thứ Linux.


cố gắng tìm nguồn nội dung của cài đặt. Ngay cả với './sinstall', nó vẫn thất bại với './sinstall': Mơ hồ ('= backtick)
Majenko

/dev/stdincũng hoạt động trên BSD và Cygwin.
dùng1686

1
|Tuy nhiên, việc sử dụng sẽ không hiệu quả (ít nhất là không chính xác), bởi vì cả hai bên của đường ống là các quy trình con riêng biệt, vì vậy các lệnh có nguồn gốc sẽ không ảnh hưởng đến trình bao hiện tại.
dùng1686

1
chỉnh sửa để phản ánh điều đó.
LawrenceC

1
Tôi thích /dev/stdinthủ thuật này , nhưng những gì câu trả lời của bạn thực tế tương đương với một đồng bằng source ./settingsmà không thực hiện nó. Người ta có thể sử dụng một tài liệu ở đây để khắc phục điều này : source /dev/stdin <<EOF \n $(./settings) \n EOF.
tlwhitec

0

Muốn cung cấp một viễn cảnh khác ở đây, vì các câu trả lời khác tạo tệp và không trực tiếp lấy từ stdin. Tôi có một số bản dựng cần gửi một số thông tin môi trường đã chuẩn bị cho nhiều tập lệnh. Những gì tôi đang làm là chuẩn bị một loạt các phép gán biến tương thích Bash trong một chuỗi:

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

Khi tôi chuẩn bị thực thi tập lệnh, tôi Base64 mã hóa chuỗi đa dòng ở trên và đưa nó vào tập lệnh shell của mình:

echo base64EncodedParameters | build.sh

Trong build.sh tôi đọc từ stdin, giải mã base64 và đánh giá kết quả.

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

echo "Hello ${Var1} ${Var2}"
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.