tập lệnh bash [x $ 1 = x]


21

Tôi đang đọc kịch bản bash Tôi không hiểu chuyện gì đang xảy ra ở đó.

#!/bin/sh
[ x$1 = x ] 

Điều gì đang xảy ra trên dòng thứ hai và [ x$1 = x ] có nghĩa là gì?

Câu trả lời:


27

Đó là kiểm tra $1trống, mặc dù nó nên được trích dẫn (giống hệt [ -z "$1" ]). Một số shell rất cũ không xử lý đúng các chuỗi rỗng, vì vậy các tác giả của các kịch bản di động đã áp dụng kiểu kiểm tra này. Nó không cần thiết trong nhiều thập kỷ, nhưng mọi người vẫn làm theo cách đó bởi vì mọi người vẫn làm theo cách đó.


Vâng, bạn không nên làm như thế này nữa và áp dụng một phong cách hiện đại hơn. Trừ khi bạn đang làm việc trên PDP11.
MacLemon

4
Nó không nhiều về các chuỗi trống. [ x$1 = x ]vẫn chạy sai, nhưng [ "x$1" = x ]sẽ cho vỏ có một vấn đề mà $1!hay (hay -n.... [ "" = "$1" ]case $1 in "")cũng sẽ là OK mặc dù.
Stéphane Chazelas

2
@MacLemon, không cần phải đi quá xa. [ -z "$1" ][ "$1" = "" ]vẫn không hoạt động với / bin / sh của Solaris 10, trước đây có dấu gạch ngang-0,5.4.
Stéphane Chazelas

1
thêm +1 cho câu cuối cùng!
glenn jackman

1
@glennjackman, câu cuối cùng không đúng. Solaris 10 vẫn là phiên bản Solaris được triển khai rộng rãi nhất và [ "$1" = "" ]vẫn không hoạt động với phiên bản này /bin/sh(mặc dù bạn không muốn sử dụng /usr/xpg4/bin/shở đó /bin/sh). dash đã được sửa trong vấn đề đó vào tháng 1 năm 2009.
Stéphane Chazelas

8

Dấu ngoặc vuông biểu thị một bài kiểm tra , do đó, [ x$1 = x]không có ifhoặc một cái gì đó tương tự là vô nghĩa, mặc dù về mặt cú pháp thì ok.

Nó có nghĩa là đánh giá thành đúng nếu x$1mở rộng thành xvà sai, nhưng vì nó không được trích dẫn, nếu $1là (ví dụ) "hey x", trình bao sẽ thấy x = x, vì vậy công trình này vẫn không an toàn.

Mục đích của việc x = xkiểm tra là xác định xem một biến có trống không. Một cách phổ biến hơn để làm điều này là chỉ sử dụng dấu ngoặc kép:

if [ "$1" = "" ]; then

Toán tử kiểm tra Bash -z-ncũng có thể được sử dụng, nhưng chúng ít di động hơn với các loại đạn khác. 1

Lý do cho các trích dẫn, hoặc là x$1, vì phía bên trái không mở rộng thành không có gì, đó sẽ là một lỗi cú pháp:

if [  = x ]  # No good!
if [ "" =  "" ] # Okay.
if [ x = x ] # Also okay.

1. Trên thực tế, testcó thể là tiện ích độc lập nhưng hầu hết các shell thực hiện nó dưới dạng tích hợp; kiểm tra sự khác biệt giữa which testtype test. Trên GNU / Linux man testtuyên bố đề cập đến tích hợp sẵn, nhưng nếu bạn gọi (ví dụ) /usr/bin/test, tiện ích đó dường như thực hiện các tính năng được ghi trong trang hướng dẫn, bao gồm -z-n.


1
[ x$1 = x ]cũng sẽ đánh giá là đúng nếu $1là ví dụ " -o x". Hãy thử sh -xc '[ x$1 = x ] && echo yes' sh ' -o x'. [ x$1 = x ]là sai và không có ý nghĩa.
Stéphane Chazelas

@ StéphaneChazelas Cảm ơn SC - đã chỉnh sửa (đoạn 2).
goldilocks

bạn không cần ifphải sử dụng test, bạn có thể sử dụng nó trước khi &&, ||hoặc sau whilehoặc kiểm tra kết quả bằng cách sử dụng$?
Jasen

8
[ x$1 = x ]

Chỉ có ý nghĩa trong zsh. Điều đó so sánh sự kết hợp xvới đối số đầu tiên của kịch bản x. Vì vậy, [lệnh trả về true nếu $1trống hoặc không được cung cấp.

[ $1 = "" ]

Sẽ không hoạt động bởi vì, zshkhi một biến rỗng không được trích dẫn trong ngữ cảnh danh sách, nó sẽ mở rộng thành không có đối số nào thay vì một đối số trống, vì vậy nếu $1không được đặt hoặc trống, [lệnh sẽ chỉ nhận dưới dạng đối số [, =chuỗi rỗng và ]nó không thể có ý nghĩa [ -z "$1" ]hoặc [ "$1" = "" ]sẽ ổn dù như trong vỏ POSIX.

Trong shell của Bourne-like / POSIX, [ x$1 = x ]không có nghĩa gì. Đó là toán tử split + global bằng cách nào đó được áp dụng cho việc ghép xvà đối số đầu tiên của tập lệnh hy vọng rằng kết quả =x, và ]tạo thành một biểu thức kiểm tra hợp lệ cho [lệnh.

Ví dụ, nếu kịch bản đã được thông qua một " = x -o x ="đối số, [sẽ nhận được những lý lẽ: [, x, =, x, -o, x, =, x, ], mà [sẽ hiểu như so sánh xvới xxvới xvà trở thành sự thật.

Nếu $1"* *", thì shell sẽ chuyển đến [lệnh danh sách các tệp trong thư mục hiện tại có tên bắt đầu bằng x(mở rộng toàn cầu x*), sau đó danh sách các tệp không bị ẩn (mở rộng *) ... [không có khả năng để làm cho bất kỳ ý nghĩa ra khỏi. Các trường hợp duy nhất có thể làm bất cứ điều gì hợp lý là nếu $1không chứa ký tự đại diện hoặc ký tự trống.

Bây giờ, những gì bạn đôi khi tìm thấy là mã như:

[ "x$1" = x ]

Điều đó được sử dụng để kiểm tra nếu $1trống hoặc không đặt.

Cách thông thường để kiểm tra biến rỗng hoặc không đặt là:

[ -z "$1" ]

Nhưng điều đó không thành công đối với một số giá trị $1như =trong một số [triển khai (không phải POSIX) như tích hợp trong vỏ Bourne như /bin/shtrên Solaris 10 và trước đó hoặc một số phiên bản cũ của dash(lên tới 0,5,4) hoặc shcủa một số BSD.

Đó là bởi vì [nhìn thấy [, -z, =, ]và phàn nàn về việc thiếu đối số cho các =nhà điều hành nhị phân thay vì tìm hiểu nó như là -ztoán tử đơn hạng áp dụng cho các =chuỗi.

Tương tự, [ "$1" = "" ]thất bại đối với một số triển khai [nếu $1!hoặc (.

Trong các shell / [triển khai:

[ "x$1" = x ]

luôn luôn là một thử nghiệm hợp lệ bất kể giá trị của $1, vì vậy:

[ "" = "$1" ]

và:

[ -z "${1:+x}" ]

case $1 in "") ...; esac

Tất nhiên, nếu bạn muốn kiểm tra xem không có đối số nào được cung cấp, bạn sẽ làm:

[ "$#" -eq 0 ]

Đó là, bạn kiểm tra số lượng đối số được truyền cho tập lệnh.

Lưu ý rằng hiện nay, [ -z "$var" ]được quy định rõ ràng bởi POSIX và không thể thất bại trong tuân thủ QTI [triển khai (và bash's [là và đã được trong nhiều thập niên). Vì vậy, bạn sẽ có thể dựa vào nó trong POSIX sh hoặc bashscript.


0

x$1đang nối hai chuỗi x$1nếu $ 1 trống, x $ 1 bằng x và [x $ 1 = x] sẽ là kết quả đúng. x = yđược sử dụng để so sánh chuỗi trong sh


2
Không x$1được trích dẫn, vì vậy việc phân tách và tạo khối được thực hiện trên những cái đó.
Stéphane Chazelas

0

[ x$1 = x ]là đúng nếu $1unset / null / trống hay không.
Hãy thử bản thân với:
TEST= ;[ x$TEST = x] && echo "TEST is unset"

TEST=lolz ;[ x$TEST = x ] && echo "TEST is unset"


1
[ x$1 = x ]cũng đúng nếu $1là ví dụ " -o x". Hãy thử sh -xc '[ x$1 = x ] && echo yes' sh ' -o x'. [ x$1 = x ]là sai và không có ý nghĩa.
Stéphane Chazelas
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.