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?

Ricardo Marimon
sumber

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

ghostdog74
sumber
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
Jadav Bheda
sumber
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).

Dijeda sampai pemberitahuan lebih lanjut.
sumber
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
manish_s
sumber
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

sibaz
sumber
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)'
bukzor
sumber
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"
Jonathan Leffler
sumber
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" }'
kokane
sumber
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
speefak
sumber
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