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


Jawaban:


146
VAR=$(scan)

Cara yang persis sama untuk program.


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


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
}

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
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.