Đọc một biến trong bash với giá trị mặc định


191

Tôi cần đọc một giá trị từ thiết bị đầu cuối trong tập lệnh bash. Tôi muốn có thể cung cấp một giá trị mặc định mà người dùng có thể thay đổi.

# Please enter your name: Ricardo^

Trong kịch bản này, lời nhắc là "Vui lòng nhập tên của bạn:" giá trị mặc định là "Ricardo" và con trỏ sẽ ở sau giá trị mặc định. Có cách nào để làm điều này trong một kịch bản bash không?

Câu trả lời:


278

bạn có thể sử dụng mở rộng tham số, vd

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

Bao gồm giá trị mặc định trong lời nhắc giữa các dấu ngoặc là một quy ước khá phổ biến


7
Tôi cuối cùng đã làm một cái gì đó dựa trên điều này. Đọc vào một biến tạm thời inputvà sau đó sử dụng name=${input:-$name}.
Ricardo Marimon

41
Điều này không thực sự trả lời câu hỏi. Giá trị mặc định sẽ được hiển thị trong lời nhắc.
Tiến sĩ Person Person II

3
và sẽ name=${!input:-$name}làm gì?
Harry Lee

8
@ Dr.PersonPersonII - bạn có thể thêm giá trị mặc định bằng cách thực hiện như sau: read -p "Nhập tên máy chủ từ xa [$ remote_host_default]:" remote_host remote_host = $ {remote_host: - $ remote_host_default}
Dobler

4
$1trở thành${1:-some_default_string}
ThorSummoner

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

echo $NAME

1
Câu trả lời chính xác! Tôi chỉ muốn đề cập rằng tôi đã gặp rắc rối với nó, bởi vì tôi đã không nhìn thấy khoảng trống giữa "Ricardo" và NAME, nhưng một khi tôi đã tìm ra điều đó .... ma thuật ! Cảm ơn bạn!
Ông Mikkél

40
thật không may -i không phải là một tùy chọn hợp lệ cho OSX 10.7
không xác định

3
@BrianMortenson Bạn có thể nâng cấp bash bằng homebrew: stackoverflow.com/questions/16416195/
mẹo

2
Câu trả lời này cho thấy cách làm cho công việc này hoạt động trên OS X (Bash 3.x): stackoverflow.com/questions/22634065/iêu
Christoph Thúchnig

3
Chỉ cần lưu ý rằng -edường như là bắt buộc để cho phép -ithực sự hoạt động
MestreLion

48

Trong Bash 4:

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

Điều này sẽ hiển thị tên sau lời nhắc như thế này:

Please enter your name: Ricardo

với con trỏ ở cuối tên và cho phép người dùng chỉnh sửa nó. Dòng cuối cùng là tùy chọn và buộc tên phải là mặc định ban đầu nếu người dùng xóa đầu vào hoặc mặc định (gửi null).


Không thể sử dụng bash4 vì nó không chuẩn trong các bản phân phối debian. Tôi cần một cái gì đó sẽ làm việc mà không gặp nhiều rắc rối.
Ricardo Marimon

1
không cần dòng mã cuối cùng, chỉ cần sử dụng namethay vì inputtrong readlệnh.
RNA

1
@RNAer: Bằng cách sử dụng biến phụ, giá trị của $nameđược giữ nguyên nếu người dùng xóa giá trị được đề xuất (và do đó nhập chuỗi null). Tất cả phụ thuộc vào nhu cầu của bạn là gì. Tôi đã nói nhiều như vậy trong câu trả lời của tôi. Tuy nhiên, bạn đúng, rằng tôi có thể đã rõ ràng hơn và nói rằng nếu dòng tùy chọn không được sử dụng thì biến đó có thể là name.
Tạm dừng cho đến khi có thông báo mới.

1
@DennisWilliamson: Bạn nói đúng. Đó là một thực hành tốt nếu đó là những gì một người muốn.
RNA

16

Mã số:

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"

Chạy mẫu:

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

Tôi thích điều này bởi vì nó tuân theo quy ước mà tôi thấy trong rất nhiều tập lệnh shell trong đó giá trị mặc định nằm trong dấu ngoặc vuông trước dấu hai chấm. Cảm ơn!!!
thái

16

Tôi tìm thấy câu hỏi này, tìm kiếm một cách để trình bày một cái gì đó như:

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

Sử dụng các ví dụ trên tôi đã suy luận điều này: -

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

Hy vọng rằng sẽ giúp ai đó không phải suy nghĩ logic, nếu họ gặp phải vấn đề tương tự


Rất đẹp. Thậm chí có thể cải thiện một chút để lặp lại câu hỏi nếu ai đó chỉ nhập "k" hoặc một cái gì khác ngoài các lựa chọn đã cho.
erikbwork

1
Tôi chỉ viết bình luận này sau khi bị ngứa. Bây giờ tôi có một hàm shell, bao gồm ở trên, và tôi có xu hướng sử dụng nó. Shell dường như không lặp lại một cách độc đáo, vì vậy tôi cố gắng tránh nó. Tôi có thể kiểm tra kết quả từ chức năng của mình và thử thêm một lần nữa, nhưng về cơ bản, tôi đang viết các công cụ quản trị nơi mọi thứ có thể sai, vì vậy tôi muốn quản trị viên có thể dừng tập lệnh một cách sạch sẽ bất cứ lúc nào.
sibaz

11

Tôi vừa mới sử dụng mẫu này, mà tôi thích:

read name || name='(nobody)'

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

Đặt mặc định; in nó; đọc một giá trị mới; nếu có một giá trị mới, sử dụng nó thay cho giá trị mặc định. Có (hoặc là) một số biến thể giữa hệ vỏ và hệ thống về cách chặn dòng mới ở cuối dấu nhắc. Ký hiệu '\ c' dường như hoạt động trên MacOS X 10.6.3 với bash 3.x và hoạt động trên hầu hết các biến thể của Unix có nguồn gốc từ System V, sử dụng shell Bourne hoặc Korn.

Cũng lưu ý rằng người dùng có thể sẽ không nhận ra những gì đang diễn ra đằng sau hậu trường; dữ liệu mới của họ sẽ được nhập sau khi tên đã có trên màn hình. Có thể tốt hơn để định dạng nó:

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

printfdễ mang theo hơnecho
ghostdog74

3
@ ghostdog74: có lẽ vậy; những người trong chúng ta đã học lập trình shell hơn 25 năm trước có một thời gian khó khăn để tìm ra cách thực hành nào của chúng tôi vẫn có liên quan. Dường như bash đã viết lại tất cả mọi thứ. Tôi biết printf đã xuất hiện được một thời gian như một lệnh - tôi rất hiếm khi sử dụng nó, mặc dù (có lẽ - không bao giờ?). Tôi có ấn tượng rằng tôi nên im lặng trên vỏ cho đến khi tôi học lại được bash. 'Thật buồn cười; phần mềm tôi làm việc có các kịch bản shell không hoạt động tốt - nhưng rắc rối không phải là bash-isms. Tôi cảm thấy chán ngấy với việc sửa chữa ' if (test -z "$xxx"); ...' và các vỏ C khác.
Jonathan Leffler

Tôi ngạc nhiên khi bash hỗ trợ \c, vì nó cũng hỗ trợ echo -n! Tuy nhiên, bạn phải thêm -eđể có được tiếng vang của bash để giải thích các lối thoát. Tôi đoán \clà cho những thứ chưa được trả:echo -e "Syntax slightly off\c, but I've learned so much from what you've shared. Thanks, @JonathanLeffler!"
jpaugh

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
vui lòng thêm giải thích cho câu trả lời của bạn.
Sufiyan Ghori

-1

Tham số -e và -t không hoạt động cùng nhau. tôi đã thử một số biểu thức và kết quả là đoạn mã sau:

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

Câu trả lời của bạn không liên quan nhiều đến câu hỏi, phải không?
Lôi

công việc của nó là sử dụng tham số -e và -t. dòng mã này (-e và -i cho giá trị mặc định): đọc -e -p "Nhập tên của bạn:" -i "Ricardo" NAME không hoạt động với bộ đếm ngược (-t)
speefak

Vâng, nhưng điều đó không được hỏi trong câu hỏi, phải không?
gniourf_gniourf

3
Những gì bạn có thể làm là hỏi một câu hỏi mới, và tự trả lời nó ;). Điều này được cho phép trên SO! nhưng chúng tôi không muốn làm ô nhiễm các câu hỏi khác với những thứ không liên quan.
gniourf_gniourf
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.