Bagaimana cara menetapkan output dari suatu fungsi ke variabel menggunakan bash?

98

Saya memiliki fungsi bash yang menghasilkan beberapa keluaran:

function scan {
  echo "output"
}

Bagaimana cara menetapkan keluaran ini ke variabel?

yaitu. VAR = scan (tentu saja ini tidak berhasil - ini membuat VAR sama dengan string "scan")

Brent
sumber
1
Terkait: stackoverflow.com/q/3236871/435605
AlikElzin-kilaka

Jawaban:

146
VAR=$(scan)

Cara yang persis sama untuk program.

Robert Obryk
sumber
3
Saya menemukan bahwa baris baru dihilangkan ketika saya melakukan "echo $ VAR". Sebaliknya, jika saya mengutip $ VAR, baris baru tersebut dipertahankan.
Brent
2
Itu tidak 100% benar. Substitusi perintah selalu menghapus baris baru yang tertinggal.
TheBonsai
7
Ini menciptakan subkulit; apakah ada cara untuk melakukannya di shell yang sama?
Penebusan Terbatas
24

Anda dapat menggunakan fungsi bash dalam perintah / pipelines seperti halnya Anda menggunakan program biasa. Fungsi ini juga tersedia untuk subkulit dan secara transitif, Substitusi Perintah:

VAR=$(scan)

Merupakan cara yang tepat untuk mencapai hasil yang Anda inginkan dalam banyak kasus. Saya akan menjelaskan kasus-kasus khusus di bawah ini.

Mempertahankan Garis Baru yang tertinggal:

Salah satu efek samping (biasanya membantu) dari Command Substitution adalah ia akan menghapus sejumlah baris baru yang tertinggal. Jika seseorang ingin mempertahankan garis baru yang tertinggal, seseorang dapat menambahkan karakter dummy ke keluaran subkulit, dan kemudian menghapusnya dengan perluasan parameter.

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}---"

cetakan (3 baris baru disimpan):

output


---

Gunakan parameter output: menghindari subkulit (dan mempertahankan baris baru)

Jika fungsi mencoba untuk mencapai adalah untuk "mengembalikan" string menjadi variabel, dengan bash v4.3 dan lebih tinggi, seseorang dapat menggunakan apa yang disebut a nameref. Namerefs memungkinkan suatu fungsi untuk mengambil nama dari satu atau lebih parameter output variabel. Anda dapat menugaskan sesuatu ke variabel nameref, dan itu seperti jika Anda mengubah variabel itu 'menunjuk ke / referensi'.

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}==="

cetakan:

output

===

Formulir ini memiliki beberapa keunggulan. Yakni, ini memungkinkan fungsi Anda untuk mengubah lingkungan pemanggil tanpa menggunakan variabel global di mana-mana.

Catatan: menggunakan nameref dapat meningkatkan kinerja program Anda jika fungsi Anda sangat bergantung pada bash bawaan, karena ini menghindari pembuatan subkulit yang dibuang setelahnya. Ini umumnya lebih masuk akal untuk fungsi kecil yang sering digunakan kembali, misalnya fungsi yang diakhiri denganecho "$returnstring"

Ini relevan. https://stackoverflow.com/a/38997681/5556676

init_js
sumber
0

Saya pikir init_js harus menggunakan mendeklarasikan daripada lokal!

function scan3() {
    declare -n outvar=$1    # -n makes it a nameref.
    local nl=$'\x0a'
    outvar="output${nl}${nl}"  # two total. quotes preserve newlines
}
Hamid Reza Hasani
sumber
yang localbuiltin akan menerima opsi bahwa declarebuiltin akan menerima. dari tes cepat, juga terlihat seolah-olah declare -ndalam lingkup fungsi juga memberikan ruang lingkup lokal variabel. sepertinya keduanya dapat dipertukarkan di sini.
init_js