Baca variabel dalam bash dengan nilai default


192

Saya perlu membaca nilai dari terminal dalam skrip bash. Saya ingin dapat memberikan nilai default yang dapat diubah pengguna.

# Please enter your name: Ricardo^

Dalam skrip ini promptnya adalah "Silakan masukkan nama Anda:" nilai defaultnya adalah "Ricardo" dan kursornya akan setelah nilai default. Apakah ada cara untuk melakukan ini dalam skrip bash?

Jawaban:


280

Anda dapat menggunakan ekspansi parameter mis

read -p "Enter your name [Richard]: " name
name=${name:-Richard}
echo $name

Termasuk nilai default di prompt antara tanda kurung adalah konvensi yang cukup umum


7
Saya akhirnya melakukan sesuatu berdasarkan ini. Membaca ke dalam variabel temp inputdan kemudian menggunakan name=${input:-$name}.
Ricardo Marimon

41
Ini sebenarnya tidak menjawab pertanyaan. Nilai default harus ditampilkan pada prompt.
Dr. Person Person II

3
dan apa yang akan name=${!input:-$name}dilakukan?
Harry Lee

8
@ Dr.PersonPersonII - Anda dapat menambahkan nilai default dengan melakukan sesuatu seperti ini: baca -p "Masukkan nama host jarak jauh [$ remote_host_default]:" remote_host remote_host = $ {remote_host: - $ remote_host_default}
Dobler

5
$1menjadi${1:-some_default_string}
ThorSummoner

162
read -e -p "Enter Your Name:" -i "Ricardo" NAME

echo $NAME

1
Jawaban bagus! Saya hanya ingin menyebutkan bahwa saya mengalami masalah dengan itu, karena saya tidak melihat ruang antara "Ricardo" dan NAME, tetapi begitu saya menemukan jawabannya .... ajaib ! Terima kasih!
Tuan Mikkél

40
sayangnya -i bukan pilihan yang valid untuk OSX 10.7
tidak ditentukan

3
@BrianMortenson Anda dapat memutakhirkan bash menggunakan homebrew: stackoverflow.com/questions/16416195/…
antonagestam

2
Jawaban ini menunjukkan bagaimana membuat ini berfungsi pada OS X (Bash 3.x): stackoverflow.com/questions/22634065/…
Christoph Petschnig

3
Perhatikan saja bahwa -etampaknya wajib -iuntuk benar-benar berfungsi
MestreLion

49

Dalam Bash 4:

name="Ricardo"
read -e -i "$name" -p "Please enter your name: " input
name="${input:-$name}"

Ini menampilkan nama setelah prompt seperti ini:

Please enter your name: Ricardo

dengan kursor di akhir nama dan memungkinkan pengguna untuk mengeditnya. Baris terakhir adalah opsional dan memaksa nama menjadi default asli jika pengguna menghapus input atau default (mengirimkan nol).


Tidak dapat menggunakan bash4 karena ini bukan standar dalam distribusi debian. Saya butuh sesuatu yang akan bekerja tanpa banyak kesulitan.
Ricardo Marimon

1
tidak perlu untuk baris kode terakhir, cukup gunakan namealih-alih inputdalam readperintah.
RNA

2
@RNAer: Dengan menggunakan variabel tambahan, nilai $namediawetkan jika pengguna menghapus nilai yang diusulkan (dan dengan demikian memasukkan string nol). Itu semua tergantung pada apa kebutuhan Anda. Saya mengatakan banyak hal dalam jawaban saya. Anda benar, meskipun, bahwa saya bisa lebih eksplisit dan mengatakan bahwa jika garis opsional tidak digunakan maka variabel bisa saja name.
Dijeda sampai pemberitahuan lebih lanjut.

1
@ DennisWilliamson: Anda benar. Ini praktik yang baik jika itu yang diinginkan.
RNA

16

Kode:

IN_PATH_DEFAULT="/tmp/input.txt"
read -p "Please enter IN_PATH [$IN_PATH_DEFAULT]: " IN_PATH
IN_PATH="${IN_PATH:-$IN_PATH_DEFAULT}"

OUT_PATH_DEFAULT="/tmp/output.txt"
read -p "Please enter OUT_PATH [$OUT_PATH_DEFAULT]: " OUT_PATH
OUT_PATH="${OUT_PATH:-$OUT_PATH_DEFAULT}"

echo "Input: $IN_PATH Output: $OUT_PATH"

Contoh dijalankan:

Please enter IN_PATH [/tmp/input.txt]: 
Please enter OUT_PATH [/tmp/output.txt]: ~/out.txt
Input: /tmp/input.txt Output: ~/out.txt

Saya suka ini karena mengikuti konvensi yang saya lihat di banyak skrip shell di mana nilai default adalah dalam tanda kurung siku sebelum titik dua. Terima kasih!!!
morphatic

16

Saya menemukan pertanyaan ini, mencari cara untuk menyajikan sesuatu seperti:

Something interesting happened.  Proceed [Y/n/q]:

Dengan menggunakan contoh di atas saya menyimpulkan ini: -

echo -n "Something interesting happened.  "
DEFAULT="y"
read -e -p "Proceed [Y/n/q]:" PROCEED
# adopt the default, if 'enter' given
PROCEED="${PROCEED:-${DEFAULT}}"
# change to lower case to simplify following if
PROCEED="${PROCEED,,}"
# condition for specific letter
if [ "${PROCEED}" == "q" ] ; then
  echo "Quitting"
  exit
# condition for non specific letter (ie anything other than q/y)
# if you want to have the active 'y' code in the last section
elif [ "${PROCEED}" != "y" ] ; then
  echo "Not Proceeding"
else
  echo "Proceeding"
  # do proceeding code in here
fi

Harapan itu membantu seseorang untuk tidak harus memikirkan logika, jika mereka menemui masalah yang sama


Sangat bagus. Bahkan dapat ditingkatkan sedikit untuk mengulang pertanyaan jika seseorang hanya memasukkan "k" atau sesuatu yang lain daripada pilihan yang diberikan.
erikbwork

1
Saya hanya menulis komentar ini setelah gatal. Saya sekarang memiliki fungsi shell, yang termasuk di atas, dan saya cenderung menggunakannya. Shell sepertinya tidak berputar dengan baik, jadi aku mencoba menghindarinya. Saya mungkin menguji hasil dari fungsi saya, dan mencoba sekali lagi, tetapi pada dasarnya, saya menulis alat admin di mana ada yang salah, jadi saya ingin admin dapat menghentikan skrip dengan bersih di titik mana pun.
sibaz

11

Saya baru saja menggunakan pola ini, yang saya sukai:

read name || name='(nobody)'

6
name=Ricardo
echo "Please enter your name: $name \c"
read newname
[ -n "$newname" ] && name=$newname

Tetapkan default; cetak ini; baca nilai baru; jika ada nilai baru, gunakan di tempat default. Ada (atau pernah) beberapa variasi antara cangkang dan sistem tentang cara menekan baris baru di akhir prompt. Notasi '\ c' tampaknya berfungsi pada MacOS X 10.6.3 dengan bash 3.x, dan bekerja pada sebagian besar varian Unix yang berasal dari System V, menggunakan cangkang Bourne atau Korn.

Perhatikan juga bahwa pengguna mungkin tidak akan menyadari apa yang terjadi di balik layar; data baru mereka akan dimasukkan setelah nama sudah ada di layar. Mungkin lebih baik untuk memformatnya:

echo "Please enter your name ($name): \c"

printflebih portabel dariecho
ghostdog74

3
@ ghostdog74: mungkin begitu; kita yang telah mempelajari pemrograman shell lebih dari 25 tahun yang lalu mengalami kesulitan untuk mencari tahu praktik mana yang masih relevan. Semakin terlihat seperti bash telah menulis ulang tentang semuanya. Saya tahu printf telah ada beberapa saat sebagai perintah - saya sangat jarang menggunakannya, (mungkin - tidak pernah?). Saya mendapat kesan saya harus tutup mulut sampai saya belajar (bash). Ini lucu; perangkat lunak tempat saya bekerja memiliki skrip shell yang tidak berfungsi dengan baik - tetapi masalahnya bukan bash-isme. Saya hanya muak dengan memperbaiki ' if (test -z "$xxx"); ...' dan shellisms C lainnya.
Jonathan Leffler

Saya kagum bahwa bash mendukung \c, karena itu juga mendukung echo -n! Namun, Anda harus menambahkan -euntuk mendapatkan gema bash untuk menafsirkan lolos. Saya kira \cuntuk hal-hal yang tidak terucapkan:echo -e "Syntax slightly off\c, but I've learned so much from what you've shared. Thanks, @JonathanLeffler!"
jpaugh

@Jonathan Leffler Sayangnya, tidak benar-benar apa yang diminta OP, setidaknya tidak pada bash versi 4.x $ bash --version GNU bash, version 4.3.33(0)-release a) "Saya ingin dapat memberikan nilai default yang dapat diubah pengguna." Anda echo "Please enter your name: $name \c"tidak memungkinkan saya untuk mengedit nilai default. b) "dan kursor akan setelah nilai default." Tidak benar juga ... Jawaban oleh @Paused hingga pemberitahuan lebih lanjut. tidak memenuhi kedua persyaratan.
Bernie Reiter

1
#Script for calculating various values in MB
echo "Please enter some input: "
read input_variable
echo $input_variable | awk '{ foo = $1 / 1024 / 1024 ; print foo "MB" }'

3
tolong tambahkan penjelasan untuk jawaban Anda.
Sufiyan Ghori

-1

Parameter -e dan -t tidak bekerja bersama. saya mencoba beberapa ekspresi dan hasilnya adalah potongan kode berikut:

QMESSAGE="SHOULD I DO YES OR NO"
YMESSAGE="I DO"
NMESSAGE="I DO NOT"
FMESSAGE="PLEASE ENTER Y or N"
COUNTDOWN=2
DEFAULTVALUE=n
#----------------------------------------------------------------#
function REQUEST ()
{
read -n1 -t$COUNTDOWN -p "$QMESSAGE ? Y/N " INPUT
    INPUT=${INPUT:-$DEFAULTVALUE}
    if  [ "$INPUT" = "y" -o "$INPUT" = "Y" ] ;then
        echo -e "\n$YMESSAGE\n"
        #COMMANDEXECUTION
    elif    [ "$INPUT" = "n" -o "$INPUT" = "N" ] ;then
        echo -e "\n$NMESSAGE\n"
        #COMMANDEXECUTION
    else
        echo -e "\n$FMESSAGE\n"
    REQUEST
    fi
}
REQUEST

Jawaban Anda tidak banyak terkait dengan pertanyaan, bukan? ...
gniourf_gniourf

ini merupakan pekerjaan untuk menggunakan parameter -e dan -t. codeline ini (-e dan -i untuk nilai default): baca -e -p "Masukkan Nama Anda:" -i "Ricardo" NAME tidak berfungsi dengan penghitung waktu mundur (-t)
speefak

Ya tapi itu tidak ditanyakan dalam pertanyaan, kan?
gniourf_gniourf

3
Yang bisa Anda lakukan adalah mengajukan pertanyaan baru, dan jawab sendiri ;). Ini diizinkan pada SO! tapi kami tidak ingin mencemari pertanyaan lain dengan hal-hal yang tidak terkait.
gniourf_gniourf
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.