Làm cách nào để gán đầu ra của một hàm cho một biến bằng cách sử dụng bash?


Câu trả lời:


144
VAR=$(scan)

Chính xác giống như cách đối với các chương trình.


3
Tôi phát hiện ra rằng các dòng mới đã bị loại bỏ khi tôi thực hiện "echo $ VAR". Thay vào đó, nếu tôi trích dẫn $ VAR, nó vẫn giữ nguyên các dòng mới.
Brent

2
Điều đó không đúng 100%. Thay thế lệnh luôn luôn tách các dòng mới theo sau.
TheBonsai

7
Điều này tạo ra một vỏ con; có cách nào để làm điều đó trong cùng một shell?
Sự Chuộc Tội Có Giới Hạn vào

24

Bạn có thể sử dụng các hàm bash trong các lệnh / đường dẫn như cách bạn sử dụng các chương trình thông thường. Các chức năng cũng có sẵn để kiểm tra con và tạm thời, Thay thế lệnh:

VAR=$(scan)

Là cách đơn giản để đạt được kết quả bạn muốn trong hầu hết các trường hợp. Tôi sẽ nêu ra những trường hợp đặc biệt dưới đây.

Duy trì các dòng mới theo sau:

Một trong những tác dụng phụ (thường hữu ích) của Thay thế Lệnh là nó sẽ loại bỏ bất kỳ số lượng dòng mới ở cuối. Nếu muốn duy trì các dòng mới ở cuối, người ta có thể nối thêm một ký tự giả vào đầu ra của vỏ con, và sau đó tách nó ra bằng cách mở rộng tham số.

function scan2 () {
    local nl=$'\x0a';  # that's just \n
    echo "output${nl}${nl}" # 2 in the string + 1 by echo
}

# append a character to the total output.
# and strip it with %% parameter expansion.
VAR=$(scan2; echo "x"); VAR="${VAR%%x}"

echo "${VAR}---"

bản in (giữ 3 dòng mới):

output


---

Sử dụng tham số đầu ra: tránh vỏ con (và duy trì các dòng mới)

Nếu những gì hàm cố gắng đạt được là "trả về" một chuỗi thành một biến, với bash v4.3 trở lên, người ta có thể sử dụng cái được gọi là a nameref. Namerefs cho phép một hàm lấy tên của một hoặc nhiều tham số đầu ra của biến. Bạn có thể gán mọi thứ cho một biến nameref và giống như thể bạn đã thay đổi biến mà nó 'trỏ tới / tham chiếu'.

function scan3() {
    local -n outvar=$1    # -n makes it a nameref.
    local nl=$'\x0a'
    outvar="output${nl}${nl}"  # two total. quotes preserve newlines
}

VAR="some prior value which will get overwritten"

# you pass the name of the variable. VAR will be modified.
scan3 VAR

# newlines are also preserved.
echo "${VAR}==="

bản in:

output

===

Hình thức này có một vài ưu điểm. Cụ thể, nó cho phép hàm của bạn sửa đổi môi trường của người gọi mà không cần sử dụng các biến toàn cục ở mọi nơi.

Lưu ý: việc sử dụng namerefs có thể cải thiện hiệu suất của chương trình của bạn rất nhiều nếu các chức năng của bạn phụ thuộc nhiều vào nội trang bash, vì nó tránh được việc tạo ra một subhell bị vứt bỏ ngay sau đó. Điều này thường có ý nghĩa hơn đối với các hàm nhỏ được sử dụng lại thường xuyên, ví dụ: các hàm kết thúc bằngecho "$returnstring"

Điều này có liên quan. https://stackoverflow.com/a/38997681/5556676


0

Tôi nghĩ rằng init_js nên sử dụng khai báo thay vì cục bộ!

function scan3() {
    declare -n outvar=$1    # -n makes it a nameref.
    local nl=$'\x0a'
    outvar="output${nl}${nl}"  # two total. quotes preserve newlines
}

các localBUILTIN sẽ chấp nhận bất kỳ tùy chọn mà các declareBUILTIN sẽ chấp nhận. từ một thử nghiệm nhanh, nó cũng giống như declare -ntrong một phạm vi hàm cũng cung cấp cho phạm vi cục bộ biến. Có vẻ như chúng có thể hoán đổi cho nhau ở đây.
init_js
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.