Làm thế nào để kiểm tra nếu một biến được đặt trong Bash?


1567

Làm thế nào để tôi biết nếu một biến được đặt trong Bash?

Ví dụ, làm cách nào để kiểm tra xem người dùng có đưa tham số đầu tiên cho hàm không?

function a {
    # if $1 is set ?
}

12
if test $# -gt 0; then printf 'arg <%s>\n' "$@"; fi.
Jens

210
Lưu ý cho người tìm giải pháp: Có nhiều câu trả lời được đánh giá cao cho câu hỏi này trả lời cho câu hỏi "có biến không trống". Các giải pháp hiệu chỉnh nhiều hơn ("là tập biến") được đề cập trong câu trả lời của Jens và Lionel bên dưới.
Nathan Kidd

8
Ngoài ra Russell Harmon và Seamus đều đúng với -vthử nghiệm của họ , mặc dù điều này dường như chỉ có trên các phiên bản mới bashvà không di động trên các vỏ.
Graeme

5
Như @NathanKidd đã chỉ ra, các giải pháp chính xác được đưa ra bởi Lionel và Jens. prosseek, bạn nên chuyển câu trả lời được chấp nhận của bạn sang một trong những câu trả lời này.
Garrett

3
... hoặc câu trả lời không chính xác có thể bị đánh giá thấp bởi những người sáng suốt hơn trong số chúng tôi, vì @prosseek không giải quyết vấn đề.
dan3

Câu trả lời:


2304

(Thông thường) Đúng cách

if [ -z ${var+x} ]; then echo "var is unset"; else echo "var is set to '$var'"; fi

trong đó ${var+x}một mở rộng tham số sẽ ước lượng thành không có gì nếu không varđược đặt và thay thế chuỗi xkhác.

Trích dẫn

Các trích dẫn có thể được bỏ qua (vì vậy chúng tôi có thể nói ${var+x}thay vì "${var+x}") bởi vì cú pháp và cách sử dụng này đảm bảo điều này sẽ chỉ mở rộng thành một cái gì đó không yêu cầu dấu ngoặc kép (vì nó mở rộng ra x(không chứa ngắt từ nên không cần trích dẫn) hoặc không có gì (kết quả [ -z ], trong đó thuận tiện đánh giá cùng một giá trị (đúng) [ -z "" ]cũng như vậy)).

Tuy nhiên, trong khi các trích dẫn có thể được bỏ qua một cách an toàn, và nó không rõ ràng ngay lập tức (điều này thậm chí không rõ ràng đối với tác giả đầu tiên của lời giải thích này cũng là một lập trình viên chính của Bash), đôi khi sẽ tốt hơn khi viết giải pháp với các trích dẫn như [ -z "${var+x}" ], với chi phí rất nhỏ có thể bị phạt tốc độ O (1). Tác giả đầu tiên cũng đã thêm điều này dưới dạng một nhận xét bên cạnh mã sử dụng giải pháp này đưa URL cho câu trả lời này, giờ đây cũng bao gồm phần giải thích lý do tại sao các trích dẫn có thể được bỏ qua một cách an toàn.

(Thường) Sai cách

if [ -z "$var" ]; then echo "var is blank"; else echo "var is set to '$var'"; fi

Điều này thường sai vì nó không phân biệt giữa một biến không được đặt và một biến được đặt thành chuỗi trống. Điều đó có nghĩa là, nếu var='', thì giải pháp trên sẽ xuất ra "var is blank".

Sự khác biệt giữa unset và "set thành chuỗi rỗng" là điều cần thiết trong các tình huống người dùng phải chỉ định một phần mở rộng hoặc danh sách các thuộc tính bổ sung và không chỉ định chúng mặc định thành một giá trị không trống, trong khi chỉ định chuỗi trống nên làm cho tập lệnh sử dụng một phần mở rộng trống hoặc danh sách các thuộc tính bổ sung.

Sự khác biệt có thể không cần thiết trong mọi kịch bản mặc dù. Trong những trường hợp đó [ -z "$var" ] sẽ tốt thôi.


29
@Garrett, chỉnh sửa của bạn đã làm cho câu trả lời này không chính xác, ${var+x}là sự thay thế chính xác để sử dụng. Sử dụng [ -z ${var:+x} ]tạo ra kết quả không khác gì [ -z "$var" ].
Graeme

11
Điều này không hoạt động. Tôi nhận được "không được đặt" bất kể var có được đặt thành giá trị hay không (được xóa bằng "unset var", "echo $ var" không tạo ra đầu ra).
Brent212

10
Đối với cú pháp của giải pháp $ {tham số + từ}, phần hướng dẫn chính thức là gnu.org/software/bash/manual/ . tuy nhiên, một lỗi trong đó, nó không đề cập rất rõ cú pháp này mà chỉ nói trích dẫn (Bỏ dấu hai chấm [":"] chỉ dẫn đến một thử nghiệm cho một tham số không được đặt. .. $ {tham số: + word} [có nghĩa là] Nếu tham số là null hoặc unset, không có gì được thay thế, nếu không thì việc mở rộng từ được thay thế.); các tham chiếu được trích dẫn pubs.opengroup.org/onlinepub/9699919799/utilities/NH (tốt để biết) có nhiều tài liệu rõ ràng hơn ở đây.
Destiny Architect

7
Có vẻ như các trích dẫn được yêu cầu khi bạn sử dụng nhiều biểu thức, ví dụ: [ -z "" -a -z ${var+x} ]bash: [: argument expectedtrong bash 4.3-ubfox (nhưng không phải là zsh). Tôi thực sự không thích câu trả lời bằng cách sử dụng cú pháp xảy ra trong một số trường hợp.
FauxFaux

41
Sử dụng một đơn giản [ -z $var ]là không "sai" hơn bỏ qua dấu ngoặc kép. Dù bằng cách nào, bạn đang đưa ra các giả định về đầu vào của mình. Nếu bạn đang coi một chuỗi rỗng là unset, đó [ -z $var ]là tất cả những gì bạn cần.
nshew

910

Để kiểm tra biến chuỗi không null / khác không, tức là nếu được đặt, hãy sử dụng

if [ -n "$1" ]

Nó trái ngược với -z. Tôi thấy mình sử dụng -nnhiều hơn -z.

Bạn sẽ sử dụng nó như:

if [ -n "$1" ]; then
  echo "You supplied the first parameter!"
else
  echo "First parameter not supplied."
fi

86
Tôi thường thích [[ ]]hơn [ ], vì [[ ]]nó mạnh mẽ hơn và gây ra ít vấn đề hơn trong các tình huống nhất định (xem câu hỏi này để được giải thích về sự khác biệt giữa hai điều này). Câu hỏi đặc biệt yêu cầu một giải pháp bash và không đề cập đến bất kỳ yêu cầu về tính di động.
Lưu lượng

18
Câu hỏi là làm thế nào người ta có thể thấy nếu một biến được đặt . Sau đó, bạn không thể cho rằng biến được đặt.
HelloGoodbye

7
Tôi đồng ý, []hoạt động tốt hơn đặc biệt là đối với các tập lệnh shell (không bash).
Hengjie

73
Thất bại trên set -u.
Ciro Santilli 冠状 病毒 审查 事件

63
Lưu ý rằng đó -nlà thử nghiệm mặc định, vì vậy đơn giản hơn [ "$1" ]hoặc [[ $1 ]]hoạt động tốt. Cũng lưu ý rằng với [[ ]] trích dẫn là không cần thiết .
tne

478

Dưới đây là cách kiểm tra xem một tham số không được đặt hoặc trống ("Null") hoặc được đặt với một giá trị :

+--------------------+----------------------+-----------------+-----------------+
|   Expression       |       parameter      |     parameter   |    parameter    |
|   in script:       |   Set and Not Null   |   Set But Null  |      Unset      |
+--------------------+----------------------+-----------------+-----------------+
| ${parameter:-word} | substitute parameter | substitute word | substitute word |
| ${parameter-word}  | substitute parameter | substitute null | substitute word |
| ${parameter:=word} | substitute parameter | assign word     | assign word     |
| ${parameter=word}  | substitute parameter | substitute null | assign word     |
| ${parameter:?word} | substitute parameter | error, exit     | error, exit     |
| ${parameter?word}  | substitute parameter | substitute null | error, exit     |
| ${parameter:+word} | substitute word      | substitute null | substitute null |
| ${parameter+word}  | substitute word      | substitute word | substitute null |
+--------------------+----------------------+-----------------+-----------------+

Nguồn: POSIX: Mở rộng tham số :

Trong tất cả các trường hợp được hiển thị với "thay thế", biểu thức được thay thế bằng giá trị được hiển thị. Trong tất cả các trường hợp được hiển thị với "gán", tham số được gán giá trị đó, cũng thay thế biểu thức.

Để thể hiện điều này trong hành động:

+--------------------+----------------------+-----------------+-----------------+
|   Expression       |  FOO="world"         |     FOO=""      |    unset FOO    |
|   in script:       |  (Set and Not Null)  |  (Set But Null) |     (Unset)     |
+--------------------+----------------------+-----------------+-----------------+
| ${FOO:-hello}      | world                | hello           | hello           |
| ${FOO-hello}       | world                | ""              | hello           |
| ${FOO:=hello}      | world                | FOO=hello       | FOO=hello       |
| ${FOO=hello}       | world                | ""              | FOO=hello       |
| ${FOO:?hello}      | world                | error, exit     | error, exit     |
| ${FOO?hello}       | world                | ""              | error, exit     |
| ${FOO:+hello}      | hello                | ""              | ""              |
| ${FOO+hello}       | hello                | hello           | ""              |
+--------------------+----------------------+-----------------+-----------------+

5
@Hellooodbye Có nó hoạt động: set foo; echo ${1:-set but null or unset}echos "foo"; set --; echo ${1:-set but null or unset}tiếng vang được thiết lập nhưng vô hiệu ...
Jens

4
@Hellooodbye Các tham số vị trí có thể được đặt với, uh , set:-)
Jens

95
Câu trả lời này rất khó hiểu. Bất kỳ ví dụ thực tế về cách sử dụng bảng này?
Ben Davis

12
@BenDavis Các chi tiết được giải thích trong liên kết đến tiêu chuẩn POSIX, tham chiếu chương mà bảng được lấy từ đó. Một cấu trúc tôi sử dụng trong hầu hết mọi tập lệnh tôi viết là : ${FOOBAR:=/etc/foobar.conf}đặt giá trị mặc định cho biến nếu nó không được đặt hoặc null.
Jens

1
parameterlà bất kỳ tên biến. wordlà một số chuỗi để thay thế tùy thuộc vào cú pháp nào trong bảng bạn đang sử dụng và liệu biến đó $parameterđược đặt, đặt nhưng không hoặc không đặt. Không làm cho mọi thứ phức tạp hơn, nhưng wordcũng có thể bao gồm các biến! Điều này có thể rất hữu ích để vượt qua các đối số tùy chọn được phân tách bằng một ký tự. Ví dụ: ${parameter:+,${parameter}}xuất ra một dấu phẩy được phân tách ,$parameternếu nó được đặt nhưng không phải là null. Trong trường hợp này, word,${parameter}
TrinitronX

260

Mặc dù hầu hết các kỹ thuật được nêu ở đây là chính xác, bash 4.2 hỗ trợ kiểm tra thực tế cho sự hiện diện của một biến ( man bash ), thay vì kiểm tra giá trị của biến.

[[ -v foo ]]; echo $?
# 1

foo=bar
[[ -v foo ]]; echo $?
# 0

foo=""
[[ -v foo ]]; echo $?
# 0

Đáng chú ý, cách tiếp cận này sẽ không gây ra lỗi khi được sử dụng để kiểm tra biến unset trong set -u/ set -o nounsetmode, không giống như nhiều cách tiếp cận khác, chẳng hạn như sử dụng [ -z.


9
Trong bash 4.1.2, bất kể biến có được đặt hay không, [[ -v aaa ]]; echo $?==>-bash: conditional binary operator expected -bash: syntax error near 'aaa'
Dan

32
Đối số '-v' với nội dung 'kiểm tra' đã được thêm vào trong bash 4.2.
Ti Strga

19
đối số -v đã được thêm vào như là một bổ sung cho tùy chọn shell -u (danh từ). Khi 'danh từ' được bật (set -u), shell sẽ trả về lỗi và chấm dứt, nếu nó không tương tác. $ # là tốt để kiểm tra các tham số vị trí. Tuy nhiên, các biến được đặt tên cần một số cách khác, ngoài việc ghi đè, để xác định chúng là không đặt. Thật không may là tính năng này đã đến quá muộn vì nhiều người buộc phải tương thích với phiên bản cũ hơn, trong trường hợp đó họ không thể sử dụng nó. Tùy chọn duy nhất khác là sử dụng các thủ thuật hoặc 'hack' để khắc phục nó như được hiển thị ở trên nhưng nó không phù hợp nhất.
osirisgothra

2
Lưu ý điều này không hoạt động đối với các biến được khai báo nhưng không được đặt. ví dụdeclare -a foo
miken32

17
Đây là lý do tại sao tôi tiếp tục đọc sau khi câu trả lời được chấp nhận / bình chọn cao nhất.
Joe

176

Có nhiều cách để làm điều này với một trong số đó là:

if [ -z "$1" ]

Điều này thành công nếu $ 1 là null hoặc unset


46
Có một sự khác biệt giữa tham số unset và tham số có giá trị null.
chepner

21
Tôi chỉ muốn được mô phạm và chỉ ra đây là câu trả lời ngược lại với những gì câu hỏi đặt ra. Các câu hỏi hỏi nếu biến IS được đặt, không phải nếu biến không được đặt.
Philluminati

47
[[ ]]không có gì ngoài một cạm bẫy tính di động. if [ -n "$1" ]nên được sử dụng ở đây.
Jens

73
Câu trả lời này không chính xác. Câu hỏi yêu cầu một cách để biết liệu một biến có được đặt hay không, liệu nó có được đặt thành giá trị không trống hay không. Cho foo="", $foocó một giá trị, nhưng -zsẽ chỉ báo cáo rằng nó trống rỗng. Và -z $foosẽ nổ tung nếu bạn có set -o nounset.
Keith Thompson

4
Nó phụ thuộc vào định nghĩa của "biến được đặt". Nếu bạn muốn kiểm tra xem biến có được đặt thành một chuỗi khác không hay không , thì câu trả lời mbranning là chính xác. Nhưng nếu bạn muốn kiểm tra xem biến đó có được khai báo không nhưng không được khởi tạo (tức là foo=), thì câu trả lời của Russel là đúng.
Lưu lượng

77

Tôi luôn luôn tìm thấy bảng POSIX trong câu trả lời khác chậm, vì vậy đây là của tôi về nó:

   +----------------------+------------+-----------------------+-----------------------+
   |   if VARIABLE is:    |    set     |         empty         |        unset          |
   +----------------------+------------+-----------------------+-----------------------+
 - |  ${VARIABLE-default} | $VARIABLE  |          ""           |       "default"       |
 = |  ${VARIABLE=default} | $VARIABLE  |          ""           | $(VARIABLE="default") |
 ? |  ${VARIABLE?default} | $VARIABLE  |          ""           |       exit 127        |
 + |  ${VARIABLE+default} | "default"  |       "default"       |          ""           |
   +----------------------+------------+-----------------------+-----------------------+
:- | ${VARIABLE:-default} | $VARIABLE  |       "default"       |       "default"       |
:= | ${VARIABLE:=default} | $VARIABLE  | $(VARIABLE="default") | $(VARIABLE="default") |
:? | ${VARIABLE:?default} | $VARIABLE  |       exit 127        |       exit 127        |
:+ | ${VARIABLE:+default} | "default"  |          ""           |          ""           |
   +----------------------+------------+-----------------------+-----------------------+

Lưu ý rằng mỗi nhóm (có và không có dấu hai chấm trước) có cùng trường hợp tập hợpkhông đặt , vì vậy điều duy nhất khác nhau là cách xử lý các trường hợp trống .

Với dấu hai chấm trước, các trường hợp trốngkhông đặt là giống hệt nhau, vì vậy tôi sẽ sử dụng những trường hợp có thể (nghĩa là sử dụng :=, không chỉ =, vì trường hợp trống không nhất quán).

Tiêu đề:

  • đặt phương tiện VARIABLElà không trống ( VARIABLE="something")
  • phương tiện trốngVARIABLE là rỗng / null ( VARIABLE="")
  • unset có nghĩa là VARIABLEkhông tồn tại ( unset VARIABLE)

Giá trị:

  • $VARIABLE có nghĩa là kết quả là giá trị ban đầu của biến.
  • "default" có nghĩa là kết quả là chuỗi thay thế được cung cấp.
  • "" có nghĩa là kết quả là null (một chuỗi rỗng).
  • exit 127 có nghĩa là tập lệnh dừng thực thi với mã thoát 127.
  • $(VARIABLE="default")có nghĩa là kết quả là giá trị ban đầu của biến chuỗi thay thế được cung cấp được gán cho biến để sử dụng trong tương lai.

1
Bạn đã sửa lỗi chỉ là những lỗi mã hóa thực tế (các trường hợp không xác định không mong muốn khi làm việc với các biến). Tôi đã thực hiện một chỉnh sửa để sửa chữa thêm một vài trường hợp trong đó đồng đô la tạo ra sự khác biệt trong việc diễn giải mô tả. BTW, tất cả các biến shell (ngoại trừ mảng) là biến chuỗi; có thể chỉ là chúng chứa một chuỗi có thể được hiểu là một số. Nói về chuỗi chỉ sương mù tin nhắn. Trích dẫn không có gì để làm với chuỗi, chúng chỉ là một thay thế để thoát. VARIABLE=""có thể được viết là VARIABLE=. Tuy nhiên, trước đây là dễ đọc hơn.
Palec

Cảm ơn vì bảng này rất hữu ích, tuy nhiên tôi đang cố gắng để thoát khỏi tập lệnh nếu không được đặt hoặc để trống. Nhưng mã thoát tôi nhận được là 1 chứ không phải 127.
Phi hành gia

64

Để xem một biến là không trống, tôi sử dụng

if [[ $var ]]; then ...       # `$var' expands to a nonempty string

Các thử nghiệm ngược lại nếu một biến là unset hoặc rỗng:

if [[ ! $var ]]; then ...     # `$var' expands to the empty string (set or not)

Để xem một biến được đặt (trống hay không trống), tôi sử dụng

if [[ ${var+x} ]]; then ...   # `var' exists (empty or nonempty)
if [[ ${1+x} ]]; then ...     # Parameter 1 exists (empty or nonempty)

Các thử nghiệm ngược lại nếu một biến không được đặt:

if [[ ! ${var+x} ]]; then ... # `var' is not set at all
if [[ ! ${1+x} ]]; then ...   # We were called with no arguments

Tôi cũng đã sử dụng điều này trong một thời gian; chỉ trong một cách giảm:[ $isMac ] && param="--enable-shared"

@Bhaskar Tôi nghĩ đó là vì câu trả lời này đã cung cấp câu trả lời cơ bản giống nhau (sử dụng ${variable+x}để đặt xiff $variableđược đặt) gần nửa năm trước. Ngoài ra, nó có nhiều chi tiết hơn giải thích tại sao nó đúng.
Mark Haferkamp

nhưng ${variable+x}ít đọc hơn (& rõ ràng)
knocte

35

Trên phiên bản hiện đại của Bash (tôi nghĩ 4.2 trở lên; tôi không biết chắc), tôi sẽ thử điều này:

if [ ! -v SOMEVARIABLE ] #note the lack of a $ sigil
then
    echo "Variable is unset"
elif [ -z "$SOMEVARIABLE" ]
then
    echo "Variable is set to an empty string"
else
    echo "Variable is set to some string"
fi

5
Cũng lưu ý rằng điều đó [ -v "$VARNAME" ]không chính xác, nhưng chỉ đơn giản là thực hiện một thử nghiệm khác. Giả sử VARNAME=foo; sau đó nó kiểm tra nếu có một biến có tên foođược đặt.
chepner

5
Lưu ý cho những người muốn tính di động, -vkhông tuân thủ POSIX
kzh

Nếu có [: -v: unexpected operator, người ta phải đảm bảo sử dụng bashthay vì sh.
koppor 28/03/2017

25
if [ "$1" != "" ]; then
  echo \$1 is set
else
  echo \$1 is not set
fi

Mặc dù đối với các đối số, thông thường tốt nhất là kiểm tra $ #, đó là số lượng đối số, theo ý kiến ​​của tôi.

if [ $# -gt 0 ]; then
  echo \$1 is set
else
  echo \$1 is not set
fi

1
Bài kiểm tra đầu tiên là lạc hậu; Tôi nghĩ rằng bạn muốn [ "$1" != "" ](hoặc [ -n "$1" ]) ...
Gordon Davisson

10
Điều này sẽ thất bại nếu $1được đặt thành chuỗi trống.
HelloGoodbye

2
Phần thứ hai của câu trả lời (đếm tham số) là một cách giải quyết hữu ích cho phần đầu tiên của câu trả lời không hoạt động khi $1được đặt thành một chuỗi trống.
Mark Berry

Điều này sẽ thất bại nếu set -o nounsetđược bật.
Flimm

21

Ghi chú

Tôi đang đưa ra một câu trả lời tập trung vào Bash vì bashthẻ.

Câu trả lời ngắn

Miễn là bạn chỉ xử lý các biến được đặt tên trong Bash, hàm này sẽ luôn cho bạn biết nếu biến đã được đặt, ngay cả khi đó là một mảng trống.

variable-is-set() {
    declare -p "$1" &>/dev/null
}

Tại sao điều này hoạt động

Trong Bash (ít nhất là từ 3.0), nếu varlà biến được khai báo / set, sau đó declare -p varxuất ra một declarelệnh sẽ đặt biến varthành bất kỳ loại và giá trị hiện tại nào và trả về mã trạng thái 0(thành công). Nếu varkhông được khai báo, sau đó declare -p varxuất ra một thông báo lỗi stderrvà trả về mã trạng thái 1. Sử dụng &>/dev/null, chuyển hướng cả thông thường stdoutstderrđầu ra /dev/null, không bao giờ được nhìn thấy và không thay đổi mã trạng thái. Do đó, hàm chỉ trả về mã trạng thái.

Tại sao các phương thức khác (đôi khi) thất bại trong Bash

  • [ -n "$var" ]: Điều này chỉ kiểm tra nếu ${var[0]}không trống. (Trong Bash, $vargiống như ${var[0]}.)
  • [ -n "${var+x}" ]: Điều này chỉ kiểm tra nếu ${var[0]}được đặt.
  • [ "${#var[@]}" != 0 ]: Điều này chỉ kiểm tra nếu ít nhất một chỉ mục $varđược đặt.

Khi phương thức này thất bại ở Bash

Đây chỉ hoạt động cho các biến được đặt tên (bao gồm $_), không chắc chắn biến đặc biệt ( $!, $@, $#, $$, $*, $?, $-, $0, $1, $2, ..., và bất kỳ tôi có thể đã quên). Vì không có cái nào trong số này là mảng, kiểu POSIX [ -n "${var+x}" ]hoạt động cho tất cả các biến đặc biệt này. Nhưng hãy cẩn thận khi gói nó trong một hàm vì nhiều biến đặc biệt thay đổi giá trị / tồn tại khi các hàm được gọi.

Shell tương thích

Nếu tập lệnh của bạn có mảng và bạn đang cố gắng làm cho nó tương thích với càng nhiều shell càng tốt, thì hãy cân nhắc sử dụng typeset -pthay vì declare -p. Tôi đã đọc rằng ksh chỉ hỗ trợ trước đây, nhưng không thể kiểm tra điều này. Tôi biết rằng Bash 3.0+ và Zsh 5.5.1 đều hỗ trợ cả hai typeset -pdeclare -p, chỉ khác nhau ở chỗ cái này là cái thay thế cho cái kia. Nhưng tôi đã không kiểm tra sự khác biệt ngoài hai từ khóa đó và tôi đã không kiểm tra các trình bao khác.

Nếu bạn cần tập lệnh của mình tương thích với POSIX sh, thì bạn không thể sử dụng mảng. Không có mảng, [ -n "{$var+x}" ]công trình.

Mã so sánh cho các phương thức khác nhau trong Bash

Hàm này bỏ đặt biến var , evallà mã đã qua, chạy thử nghiệm để xác định xem varcó được đặt bởi evalmã d hay không, và cuối cùng hiển thị mã trạng thái kết quả cho các thử nghiệm khác nhau.

Tôi bỏ qua test -v var, [ -v var ][[ -v var ]]vì họ mang lại kết quả giống với tiêu chuẩn POSIX [ -n "${var+x}" ], trong khi đòi hỏi Bash 4.2 trở lên. Tôi cũng đang bỏ quatypeset -p vì nó giống như declare -ptrong các shell mà tôi đã thử nghiệm (Bash 3.0 đến 5.0 và Zsh 5.5.1).

is-var-set-after() {
    # Set var by passed expression.
    unset var
    eval "$1"

    # Run the tests, in increasing order of accuracy.
    [ -n "$var" ] # (index 0 of) var is nonempty
    nonempty=$?
    [ -n "${var+x}" ] # (index 0 of) var is set, maybe empty
    plus=$?
    [ "${#var[@]}" != 0 ] # var has at least one index set, maybe empty
    count=$?
    declare -p var &>/dev/null # var has been declared (any type)
    declared=$?

    # Show test results.
    printf '%30s: %2s %2s %2s %2s\n' "$1" $nonempty $plus $count $declared
}

Mã trường hợp thử nghiệm

Lưu ý rằng kết quả kiểm tra có thể bất ngờ do Bash coi các chỉ số mảng không phải là số "0" nếu biến không được khai báo là mảng kết hợp. Ngoài ra, mảng kết hợp chỉ có giá trị trong Bash 4.0+.

# Header.
printf '%30s: %2s %2s %2s %2s\n' "test" '-n' '+x' '#@' '-p'
# First 5 tests: Equivalent to setting 'var=foo' because index 0 of an
# indexed array is also the nonindexed value, and non-numerical
# indices in an array not declared as associative are the same as
# index 0.
is-var-set-after "var=foo"                        #  0  0  0  0
is-var-set-after "var=(foo)"                      #  0  0  0  0
is-var-set-after "var=([0]=foo)"                  #  0  0  0  0
is-var-set-after "var=([x]=foo)"                  #  0  0  0  0
is-var-set-after "var=([y]=bar [x]=foo)"          #  0  0  0  0
# '[ -n "$var" ]' fails when var is empty.
is-var-set-after "var=''"                         #  1  0  0  0
is-var-set-after "var=([0]='')"                   #  1  0  0  0
# Indices other than 0 are not detected by '[ -n "$var" ]' or by
# '[ -n "${var+x}" ]'.
is-var-set-after "var=([1]='')"                   #  1  1  0  0
is-var-set-after "var=([1]=foo)"                  #  1  1  0  0
is-var-set-after "declare -A var; var=([x]=foo)"  #  1  1  0  0
# Empty arrays are only detected by 'declare -p'.
is-var-set-after "var=()"                         #  1  1  1  0
is-var-set-after "declare -a var"                 #  1  1  1  0
is-var-set-after "declare -A var"                 #  1  1  1  0
# If 'var' is unset, then it even fails the 'declare -p var' test.
is-var-set-after "unset var"                      #  1  1  1  1

Đầu ra thử nghiệm

Các thuật nhớ kiểm tra trong tương ứng với tiêu đề hàng đến [ -n "$var" ], [ -n "${var+x}" ], [ "${#var[@]}" != 0 ], và declare -p var, tương ứng.

                         test: -n +x #@ -p
                      var=foo:  0  0  0  0
                    var=(foo):  0  0  0  0
                var=([0]=foo):  0  0  0  0
                var=([x]=foo):  0  0  0  0
        var=([y]=bar [x]=foo):  0  0  0  0
                       var='':  1  0  0  0
                 var=([0]=''):  1  0  0  0
                 var=([1]=''):  1  1  0  0
                var=([1]=foo):  1  1  0  0
declare -A var; var=([x]=foo):  1  1  0  0
                       var=():  1  1  1  0
               declare -a var:  1  1  1  0
               declare -A var:  1  1  1  0
                    unset var:  1  1  1  1

Tóm lược

  • declare -p var &>/dev/null là (100%?) đáng tin cậy để kiểm tra các biến có tên trong Bash kể từ ít nhất 3.0.
  • [ -n "${var+x}" ] là đáng tin cậy trong các tình huống tuân thủ POSIX, nhưng không thể xử lý các mảng.
  • Các thử nghiệm khác tồn tại để kiểm tra nếu một biến là không trống và để kiểm tra các biến được khai báo trong các shell khác. Nhưng các thử nghiệm này phù hợp với cả các kịch bản Bash và POSIX.

3
Trong số các câu trả lời tôi đã thử, câu trả lời này ( declare -p var &>/dev/null) là câu duy nhất hoạt động. CẢM ƠN BẠN!
dùng1387866

2
@ mark-haferkamp Tôi đã cố chỉnh sửa câu trả lời của bạn để thêm "/" quan trọng vào mã chức năng của bạn để nó đọc ... &> /dev/nullnhưng SO sẽ không cho phép tôi chỉnh sửa một ký tự (phải> 6 ký tự - thậm chí đã thử thêm khoảng trắng nhưng nó không hoạt động). Ngoài ra, có thể đáng thay đổi chức năng để chuyển ra $1một biến có tên mẫu (ví dụ OUTPUT_DIR) vì như bạn đã chỉ ra, các biến đặc biệt như $1không hoạt động ở đây. Dù sao, nó là một chỉnh sửa quan trọng nếu không mã đang tìm cách tạo một tệp được gọi nulltrong một thư mục tương đối được gọi dev. BTW - câu trả lời tuyệt vời!
joehanna

Ngoài ra, sử dụng tên của biến không có tiền tố $ cũng hoạt động: declare -p PATH &> /dev/nulltrả về 0 khi declare -p ASDFASDGFASKDF &> /dev/nulltrả về 1. (trên bash 5.0.11 (1)
-release

1
Công việc tuyệt vời 1 từ thận trọng: declare varkhai báo var một biến nhưng nó không đặt nó theo các khía cạnh set -o nounset: Kiểm tra vớideclare foo bar=; set -o nounset; echo $bar; echo $foo
xebeche

@joehanna Cảm ơn vì đã bắt mất tích /! Tôi đã sửa nó, nhưng tôi nghĩ logic đủ khó hiểu để đảm bảo một chức năng, đặc biệt là theo nhận xét của @ xebeche. @xebeche Điều đó thật bất tiện cho câu trả lời của tôi. Có vẻ như tôi sẽ phải thử một cái gì đó như declare -p "$1" | grep =hoặc test -v "$1".
Mark Haferkamp

19

Đối với những người đang tìm cách kiểm tra unset hoặc trống khi trong tập lệnh có set -u:

if [ -z "${var-}" ]; then
   echo "Must provide var environment variable. Exiting...."
   exit 1
fi

Việc [ -z "$var" ]kiểm tra thường xuyên sẽ thất bại với var; unbound variableif set -unhưng [ -z "${var-}" ] mở rộng thành chuỗi rỗng nếu varkhông được đặt mà không bị lỗi.


Bạn đang thiếu một dấu hai chấm. Nó nên ${var:-}, không phải ${var-}. Nhưng ở Bash, tôi có thể xác nhận nó hoạt động ngay cả khi không có dấu hai chấm.
Palec

3
${var:-}${var-}có nghĩa là những thứ khác nhau. ${var:-}sẽ mở rộng thành chuỗi rỗng nếu varkhông đặt hoặc null${var-}sẽ mở rộng thành chuỗi trống nếu không đặt.
RubenLaguna

Chỉ cần học một cái gì đó mới, cảm ơn! Bỏ qua các kết quả dấu hai chấm trong một thử nghiệm chỉ cho một tham số không được đặt. Nói cách khác, nếu bao gồm dấu hai chấm, toán tử kiểm tra sự tồn tại của cả tham số và giá trị của nó không phải là null; nếu dấu hai chấm bị bỏ qua, toán tử chỉ kiểm tra sự tồn tại. Nó làm cho không có sự khác biệt ở đây, nhưng tốt để biết.
Palec

17

Bạn muốn thoát nếu nó không được đặt

Điều này làm việc cho tôi. Tôi muốn tập lệnh của mình thoát với thông báo lỗi nếu tham số không được đặt.

#!/usr/bin/env bash

set -o errexit

# Get the value and empty validation check all in one
VER="${1:?You must pass a version of the format 0.0.0 as the only argument}"

Điều này trả về với một lỗi khi nó chạy

peek@peek:~$ ./setver.sh
./setver.sh: line 13: 1: You must pass a version of the format 0.0.0 as the only argument

Chỉ kiểm tra, không có lối ra - Trống và Unset là INVALID

Hãy thử tùy chọn này nếu bạn chỉ muốn kiểm tra xem giá trị được đặt = VALID hay unset / blank = INVALID.

TSET="good val"
TEMPTY=""
unset TUNSET

if [ "${TSET:-}" ]; then echo "VALID"; else echo "INVALID";fi
# VALID
if [ "${TEMPTY:-}" ]; then echo "VALID"; else echo "INVALID";fi
# INVALID
if [ "${TUNSET:-}" ]; then echo "VALID"; else echo "INVALID";fi
# INVALID

Hoặc, Ngay cả các bài kiểm tra ngắn ;-)

[ "${TSET:-}"   ] && echo "VALID" || echo "INVALID"
[ "${TEMPTY:-}" ] && echo "VALID" || echo "INVALID"
[ "${TUNSET:-}" ] && echo "VALID" || echo "INVALID"

Chỉ kiểm tra, không có lối ra - Chỉ trống là HÓA ĐƠN

Và đây là câu trả lời cho câu hỏi. Sử dụng cái này nếu bạn chỉ muốn kiểm tra xem giá trị được đặt / trống = VALID hay unset = INVALID.

LƯU Ý, "1" trong "..- 1}" không đáng kể, nó có thể là bất cứ thứ gì (như x)

TSET="good val"
TEMPTY=""
unset TUNSET

if [ "${TSET+1}" ]; then echo "VALID"; else echo "INVALID";fi
# VALID
if [ "${TEMPTY+1}" ]; then echo "VALID"; else echo "INVALID";fi
# VALID
if [ "${TUNSET+1}" ]; then echo "VALID"; else echo "INVALID";fi
# INVALID

Bài kiểm tra ngắn

[ "${TSET+1}"   ] && echo "VALID" || echo "INVALID"
[ "${TEMPTY+1}" ] && echo "VALID" || echo "INVALID"
[ "${TUNSET+1}" ] && echo "VALID" || echo "INVALID"

Tôi dành câu trả lời này cho @ mkuity0 (ý kiến), người đã thách thức tôi trả lời chính xác câu hỏi.

Tham khảo http://pub.opengroup.org/onlinepub/9699919799/utilities/V3_chap02.html#tag_18_06_02


15

Để kiểm tra xem một biến có được đặt với giá trị không trống hay không, hãy sử dụng [ -n "$x" ] , như các biến khác đã được chỉ ra.

Hầu hết thời gian, nên xử lý một biến có giá trị trống giống như một biến không được đặt. Nhưng bạn có thể phân biệt hai nếu bạn cần: [ -n "${x+set}" ]( "${x+set}"mở rộng thành setif xđược đặt và thành chuỗi trống nếux không được đặt).

Để kiểm tra xem một tham số đã được thông qua chưa, hãy kiểm tra $#, đó là số lượng tham số được truyền cho hàm (hoặc tới tập lệnh, khi không có trong hàm) (xem câu trả lời của Paul ).


14

Đọc phần "Mở rộng tham số" của phần bash trang man. Mở rộng tham số không cung cấp thử nghiệm chung cho một biến được đặt, nhưng có một số điều bạn có thể làm với tham số nếu nó không được đặt.

Ví dụ:

function a {
    first_arg=${1-foo}
    # rest of the function
}

sẽ được đặt first_argbằng $1nếu được gán, nếu không, nó sử dụng giá trị "foo". Nếu ahoàn toàn phải lấy một tham số duy nhất và không tồn tại mặc định tốt, bạn có thể thoát với thông báo lỗi khi không có tham số nào được đưa ra:

function a {
    : ${1?a must take a single argument}
    # rest of the function
}

(Lưu ý việc sử dụng :như một lệnh null, chỉ mở rộng các giá trị của các đối số của nó. Chúng tôi không muốn làm gì với $1ví dụ này, chỉ cần thoát nếu không được đặt)


1
Tôi bối rối rằng không có câu trả lời nào khác đề cập đến sự đơn giản và thanh lịch : ${var?message}.
tripleee

Bạn lấy cái này từ đâu vậy? Tuyệt vời! Nó chỉ hoạt động! Và nó ngắn và thanh lịch! Cảm ơn bạn!
Roger

13

Trong bash, bạn có thể sử dụng -vbên trong [[ ]]nội dung:

#! /bin/bash -u

if [[ ! -v SOMEVAR ]]; then
    SOMEVAR='hello'
fi

echo $SOMEVAR

8

Sử dụng [[ -z "$var" ]]là cách dễ nhất để biết một biến đã được đặt hay chưa, nhưng tùy chọn đó-z đó không phân biệt giữa biến không đặt và biến được đặt thành chuỗi rỗng:

$ set=''
$ [[ -z "$set" ]] && echo "Set" || echo "Unset" 
Unset
$ [[ -z "$unset" ]] && echo "Set" || echo "Unset"
Unset

Tốt nhất là kiểm tra nó theo loại biến: biến env, tham số hoặc biến thông thường.

Đối với biến env:

[[ $(env | grep "varname=" | wc -l) -eq 1 ]] && echo "Set" || echo "Unset"

Đối với một tham số (ví dụ: để kiểm tra sự tồn tại của tham số $5):

[[ $# -ge 5 ]] && echo "Set" || echo "Unset"

Đối với một biến thông thường (sử dụng hàm phụ trợ, để thực hiện nó một cách tao nhã):

function declare_var {
   declare -p "$1" &> /dev/null
}
declare_var "var_name" && echo "Set" || echo "Unset"

Ghi chú:

  • $#: cung cấp cho bạn số lượng tham số vị trí.
  • declare -p: cung cấp cho bạn định nghĩa của biến được truyền dưới dạng tham số. Nếu nó tồn tại, trả về 0, nếu không, trả về 1 và in thông báo lỗi.
  • &> /dev/null: chặn đầu ra declare -pmà không ảnh hưởng đến mã trả về của nó.

5

Các câu trả lời ở trên không hoạt động khi tùy chọn Bash set -uđược bật. Ngoài ra, chúng không động, ví dụ, làm thế nào để kiểm tra biến với tên "giả" được định nghĩa? Thử cái này:

is_var_defined()
{
    if [ $# -ne 1 ]
    then
        echo "Expected exactly one argument: variable name as string, e.g., 'my_var'"
        exit 1
    fi
    # Tricky.  Since Bash option 'set -u' may be enabled, we cannot directly test if a variable
    # is defined with this construct: [ ! -z "$var" ].  Instead, we must use default value
    # substitution with this construct: [ ! -z "${var:-}" ].  Normally, a default value follows the
    # operator ':-', but here we leave it blank for empty (null) string.  Finally, we need to
    # substitute the text from $1 as 'var'.  This is not allowed directly in Bash with this
    # construct: [ ! -z "${$1:-}" ].  We need to use indirection with eval operator.
    # Example: $1="var"
    # Expansion for eval operator: "[ ! -z \${$1:-} ]" -> "[ ! -z \${var:-} ]"
    # Code  execute: [ ! -z ${var:-} ]
    eval "[ ! -z \${$1:-} ]"
    return $?  # Pedantic.
}

Liên quan: Trong Bash, làm cách nào để kiểm tra nếu một biến được xác định trong chế độ "-u"


1
Tôi muốn biết rất nhiều lý do tại sao câu trả lời này bị đánh giá thấp ... Hoạt động rất tốt cho tôi.
LavaScornedOven

Trong Bash, bạn có thể làm tương tự mà không cần eval: thay đổi eval "[ ! -z \${$1:-} ]"để đánh giá gián tiếp : [ ! -z ${!1:-} ];.

@BinaryZebra: Ý tưởng thú vị. Tôi đề nghị bạn đăng như một câu trả lời riêng biệt.
kevinarpe

Sử dụng "eval" làm cho giải pháp này dễ bị tiêm mã: $ is_var_d xác định 'x}]; tiếng vang "gotcha"> & 2; # 'gotcha
tetsujin


4

Cách ưa thích của tôi là thế này:

$ var=10
$ if ! ${var+false};then echo "is set";else echo "NOT set";fi
is set
$ unset -v var
$ if ! ${var+false};then echo "is set";else echo "NOT set";fi
NOT set

Vì vậy, về cơ bản, nếu một biến được đặt, nó sẽ trở thành "phủ định kết quả false" (what will be true= "is set").

Và, nếu không được đặt, nó sẽ trở thành "phủ định kết quả true" (vì kết quả trống ước tính true) (vì vậy sẽ kết thúc là false= "KHÔNG được đặt").


1
[[ $foo ]]

Hoặc là

(( ${#foo} ))

Hoặc là

let ${#foo}

Hoặc là

declare -p foo

1

Trong một vỏ bạn có thể sử dụng -z toán tử là True nếu độ dài của chuỗi bằng không.

Một lớp lót đơn giản để đặt mặc định MY_VARnếu nó không được đặt, nếu không, bạn có thể hiển thị thông báo:

[[ -z "$MY_VAR" ]] && MY_VAR="default"
[[ -z "$MY_VAR" ]] && MY_VAR="default" || echo "Variable already set."

0
if [[ ${1:+isset} ]]
then echo "It was set and not null." >&2
else echo "It was not set or it was null." >&2
fi

if [[ ${1+isset} ]]
then echo "It was set but might be null." >&2
else echo "It was was not set." >&2
fi

$1, $2Và lên đến $Nluôn thiết lập. Xin lỗi, đây là thất bại.

Tôi đã thử nó và nó không hoạt động, có lẽ phiên bản bash của tôi thiếu hỗ trợ cho điều đó. Idk, xin lỗi nếu tôi sai. :)

0

Tôi tìm thấy một mã (nhiều) tốt hơn để làm điều này nếu bạn muốn kiểm tra bất cứ điều gì trong $@.

nếu [[$ 1 = ""]]
sau đó
  tiếng vang '$ 1 trống'
khác
  tiếng vang '$ 1 được lấp đầy'
fi

Tại sao tất cả điều này? Mọi thứ $@tồn tại ở Bash, nhưng theo mặc định nó trống, vì vậy test -ztest -nkhông thể giúp bạn.

Cập nhật: Bạn cũng có thể đếm số lượng ký tự trong một tham số.

nếu [$ {# 1} = 0]
sau đó
  tiếng vang '$ 1 trống'
khác
  tiếng vang '$ 1 được lấp đầy'
fi

Tôi biết, nhưng đó là nó. Nếu một cái gì đó trống rỗng, bạn sẽ nhận được một lỗi! Lấy làm tiếc. : P

0
if [[ ${!xx[@]} ]] ; then echo xx is defined; fi

11
Chào mừng bạn đến với StackOverflow. Trong khi câu trả lời của bạn được đánh giá cao, tốt nhất bạn không chỉ cung cấp mã. Bạn có thể thêm lý luận vào câu trả lời của bạn hoặc một lời giải thích nhỏ? Xem trang này để biết những ý tưởng khác về việc mở rộng câu trả lời của bạn.
Celeo

0

Đây là những gì tôi sử dụng hàng ngày:

#
# Check if a variable is set
#   param1  name of the variable
#
function is_set()
{
    [[ -n "${1}" ]] && test -n "$(eval "echo "\${${1}+x}"")"
}

Điều này hoạt động tốt trong Linux và Solaris cho đến bash 3.0.

bash-3.00$ myvar="TEST"
bash-3.00$ is_set myvar ; echo $?
0
bash-3.00$ mavar=""
bash-3.00$ is_set myvar ; echo $?
0
bash-3.00$ unset myvar
bash-3.00$ is_set myvar ; echo $?
1

1
Kể từ khi Bash 2.0+ mở rộng gián tiếp có sẵn. Bạn có thể thay thế dài và phức tạp (cũng bao gồm một eval) test -n "$(eval "echo "\${${1}+x}"")"cho tương đương:[[ ${!1+x} ]]

0

Tôi thích các chức năng phụ trợ để ẩn các chi tiết thô của bash. Trong trường hợp này, làm như vậy sẽ tăng thêm độ thô (ẩn) hơn:

# The first ! negates the result (can't use -n to achieve this)
# the second ! expands the content of varname (can't do ${$varname})
function IsDeclared_Tricky
{
  local varname="$1"
  ! [ -z ${!varname+x} ]
}

Bởi vì lần đầu tiên tôi gặp lỗi trong quá trình thực hiện này (lấy cảm hứng từ câu trả lời của Jens và Lionel), tôi đã đưa ra một giải pháp khác:

# Ask for the properties of the variable - fails if not declared
function IsDeclared()
{
  declare -p $1 &>/dev/null
}

Tôi thấy nó là thẳng thắn hơn, bashy hơn và dễ hiểu / dễ nhớ hơn. Trường hợp thử nghiệm cho thấy nó là tương đương:

function main()
{
  declare -i xyz
  local foo
  local bar=
  local baz=''

  IsDeclared_Tricky xyz; echo "IsDeclared_Tricky xyz: $?"
  IsDeclared_Tricky foo; echo "IsDeclared_Tricky foo: $?"
  IsDeclared_Tricky bar; echo "IsDeclared_Tricky bar: $?"
  IsDeclared_Tricky baz; echo "IsDeclared_Tricky baz: $?"

  IsDeclared xyz; echo "IsDeclared xyz: $?"
  IsDeclared foo; echo "IsDeclared foo: $?"
  IsDeclared bar; echo "IsDeclared bar: $?"
  IsDeclared baz; echo "IsDeclared baz: $?"
}

main

Các trường hợp thử nghiệm cũng cho thấy local varkhông KHÔNG tuyên bố var (trừ khi theo sau '='). Trong một thời gian, tôi nghĩ rằng tôi đã khai báo các biến theo cách này, bây giờ tôi mới phát hiện ra rằng tôi chỉ bày tỏ ý định của mình ... Tôi đoán là không có.

IsDeclared_Tricky xyz: 1
IsDeclared_Tricky foo: 1
IsDeclared_Tricky bar: 0
IsDeclared_Tricky baz: 0
IsDeclared xyz: 1
IsDeclared foo: 1
thanh IsDeclared: 0
IsDeclared baz: 0

THƯỞNG: usecase

Tôi chủ yếu sử dụng thử nghiệm này để đưa ra (và trả lại) các tham số cho các chức năng theo cách hơi "thanh lịch" và an toàn (gần giống với giao diện ...):

#auxiliary functions
function die()
{
  echo "Error: $1"; exit 1
}

function assertVariableDeclared()
{
  IsDeclared "$1" || die "variable not declared: $1"
}

function expectVariables()
{
  while (( $# > 0 )); do
    assertVariableDeclared $1; shift
  done
}

# actual example
function exampleFunction()
{
  expectVariables inputStr outputStr
  outputStr="$inputStr world!"
}

function bonus()
{
  local inputStr='Hello'
  local outputStr= # remove this to trigger error
  exampleFunction
  echo $outputStr
}

bonus

Nếu được gọi với tất cả các yêu cầu biến được khai báo:

Chào thế giới!

khác:

Lỗi: biến không được khai báo: outputStr


0

Sau khi lướt qua tất cả các câu trả lời, điều này cũng hoạt động:

if [[ -z $SOME_VAR ]]; then read -p "Enter a value for SOME_VAR: " SOME_VAR; fi
echo "SOME_VAR=$SOME_VAR"

nếu bạn không đặt SOME_VARthay vì những gì tôi có $SOME_VAR, nó sẽ đặt nó thành một giá trị trống; $là cần thiết để làm việc này.


sẽ không hoạt động khi bạn có set -uhiệu lực sẽ in unboud variablelỗi
Michael Heuberger

0

Tóm lược

  • Sử dụng test -n "${var-}"để kiểm tra xem biến không trống (và do đó phải được xác định / đặt quá)
  • Sử dụng test ! -z "${var+}"để kiểm tra xem biến được xác định / đặt (ngay cả khi nó trống)

Lưu ý rằng trường hợp sử dụng đầu tiên là phổ biến hơn nhiều trong các kịch bản shell và đây là những gì bạn thường sẽ muốn sử dụng.

Ghi chú

  • Giải pháp này sẽ hoạt động trong tất cả các vỏ POSIX (sh, bash, zsh, ksh, dash)
  • Một số câu trả lời khác cho câu hỏi này là chính xác nhưng có thể gây nhầm lẫn cho những người chưa có kinh nghiệm về kịch bản shell, vì vậy tôi muốn cung cấp câu trả lời TLDR sẽ ít gây nhầm lẫn nhất cho những người như vậy.

Giải trình

Để hiểu cách giải pháp này hoạt động, bạn cần hiểu lệnh POSIXtest và mở rộng tham số shell POSIX ( spec ), vì vậy hãy trình bày những điều cơ bản tuyệt đối cần thiết để hiểu câu trả lời.

Lệnh kiểm tra đánh giá một biểu thức và trả về giá trị đúng hoặc sai (thông qua trạng thái thoát của nó). Toán tử -ntrả về true nếu toán hạng là một chuỗi không rỗng. Vì vậy, ví dụ, test -n "a"trả về true, trong khi test -n ""trả về false. Bây giờ, để kiểm tra xem một biến không trống (có nghĩa là nó phải được xác định), bạn có thể sử dụng test -n "$var". Tuy nhiên, một số tập lệnh shell có tập tùy chọn ( set -u) khiến bất kỳ tham chiếu nào đến các biến không xác định phát ra lỗi, vì vậy nếu biến varkhông được xác định, biểu thức $asẽ gây ra lỗi. Để xử lý trường hợp này một cách chính xác, bạn phải sử dụng mở rộng biến, điều này sẽ báo cho shell thay thế biến bằng một chuỗi thay thế nếu nó không được xác định, tránh lỗi đã nói ở trên.

Việc mở rộng biến ${var-}có nghĩa là: nếu biến varkhông được xác định (còn được gọi là "unset"), hãy thay thế nó bằng một chuỗi rỗng. Vì vậy, test -n "${var-}"sẽ trả về true nếu $varkhông trống, gần như luôn luôn là những gì bạn muốn kiểm tra trong shell script. Kiểm tra ngược lại, nếu $varkhông xác định hoặc không trống, sẽ là test -z "${var-}".

Bây giờ đến trường hợp sử dụng thứ hai: kiểm tra xem biến varcó được xác định hay không, có trống hay không. Đây là trường hợp sử dụng ít phổ biến và phức tạp hơn một chút, và tôi khuyên bạn nên đọc câu trả lời tuyệt vời của Lionels để hiểu rõ hơn về nó.


-1

Để kiểm tra xem var có được đặt hay không

var=""; [[ $var ]] && echo "set" || echo "not set"

3
Điều này sẽ thất bại nếu $varđược đặt thành chuỗi trống.
HelloGoodbye

-1

Nếu bạn muốn kiểm tra xem một biến có bị ràng buộc hay không bị ràng buộc, thì điều này vẫn hoạt động tốt, ngay cả sau khi bạn đã bật tùy chọn danh từ:

set -o noun set

if printenv variableName >/dev/null; then
    # variable is bound to a value
else
    # variable is unbound
fi

Tôi nghĩ bạn có nghĩa là set -o nounsetkhông set -o noun set. Điều này chỉ hoạt động cho các biến đã được exported. Nó cũng thay đổi cài đặt của bạn theo cách khó xử để hoàn tác.
Keith Thompson
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.