Tại sao không [-n] sai như [-n Điên]?


20

Câu hỏi của tôi là về các giá trị trả về được tạo bởi mã này:

if [ -n ]; then echo "true"; else echo "false"; fi

Bản in này true.

Kiểm tra bổ sung của nó bằng cách sử dụng [ -z ]cũng in true:

if [ -z ]; then echo "true"; else  echo "false"; fi

Trong đoạn mã trên, tại sao [ -n ]kiểm tra giả sử giá trị chuỗi không được thông qua, không phải là null?

Mã dưới đây in false. Điều này được mong đợi vì giá trị chuỗi đã truyền là null và có độ dài bằng không.

if [ -n "" ]; then echo "true"; else  echo "false"; fi

Câu trả lời:


14

[x] tương đương với [ -nx] ngay cả khi x bắt đầu với -điều kiện không có toán hạng.

$ [ -o ] ; echo $?
0
$ [ -eq ] ; echo $?
0
$ [ -n -o ] ; echo $?
0
$ [ -n -eq ] ; echo $?
0

4
Lưu ý rằng trong lịch sử, [ -t ]đã kiểm tra xem thiết bị xuất chuẩn có phải là thiết bị đầu cuối (viết tắt của từ không [ -t 1 ]) và một số shell vẫn đang thực hiện (trong trường hợp ksh93chỉ khi đó -tlà bằng chữ), vì vậy tốt hơn là sử dụng [ -n "$var" ]hơn [ "$var" ]. Dù rằng vẫn sẽ thất bại trong một số cũ testtriển khai cho các giá trị của $varnhư =, trong trường hợp này [ "" != "$var" ]hay [ "x$var" != x ]hoặc case $x in "")...có thể tốt hơn.
Stéphane Chazelas

3
Lựa chọn thú vị -oở đây. Trong một số shell như bash, -ocả hai đều là unary (kiểm tra nếu một tùy chọn được đặt) và toán tử nhị phân (hoặc), vì vậy những thứ như [ ! -o monitor ]là mơ hồ. Có phải nó đang kiểm tra rằng monitortùy chọn không được đặt, hoặc là !hoặc monitorlà các chuỗi không trống? Quy tắc POSIX quyết định: cái sau (khác với [[ ! -o monitor ]]).
Stéphane Chazelas

30

[ -n ]không sử dụng -nthử nghiệm.

Các -ntrong [ -n ]không phải là một bài kiểm tra ở tất cả. Khi chỉ có một đối số giữa [], đối số đó là một chuỗi được kiểm tra để xem nó có trống không. Ngay cả khi chuỗi đó có một đầu -, nó vẫn được hiểu là một toán hạng, không phải là một bài kiểm tra. Kể từ khi chuỗi -nlà không có sản phẩm nào - nó có chứa hai ký tự, -n, không zero characters--[ -n ] đánh giá lại là true.

Như Ignacio Vazquez-Abrams nói , nơi stringlà một đối số duy nhất, kiểm tra thực hiện trên stringtrong cũng giống như các bài kiểm tra thực hiện trên nó bằng . Khi xảy ra , không có gì đặc biệt xảy ra. Các trong và lần thứ hai trong[ string ][ -n string ]string-n-n[ -n ]-n[ -n -n ] chỉ đơn giản là chuỗi đang được thử nghiệm cho sự trống rỗng.

Khi chỉ có một đối số giữa [], đối số đó luôn là một chuỗi được kiểm tra về sự không khinh suất, ngay cả khi nó xảy ra được đặt tên giống như một thử nghiệm. Tương tự như vậy, khi có hai đối số giữa [và đối số ]thứ nhất là -n, đối số thứ hai luôn là một chuỗi được kiểm tra cho sự không khinh suất, ngay cả khi nó được đặt tên giống như một bài kiểm tra. Điều này chỉ đơn giản là vì cú pháp [khẳng định rằng một đối số duy nhất giữa []sau -nlà một toán hạng chuỗi.

Vì lý do tương tự mà [ -n ]không sử dụng -nthử nghiệm, [ -z ]không sử dụng -zthử nghiệm.


Bạn có thể tìm hiểu thêm về [trong bashbằng cách kiểm tra sự giúp đỡ cho nó. Lưu ý rằng đó là một vỏ dựng sẵn :

$ type [
[ is a shell builtin

Do đó, bạn có thể chạy help [để nhận trợ giúp về nó:

$ help [
[: [ arg... ]
    Evaluate conditional expression.

    This is a synonym for the "test" builtin, but the last argument must
    be a literal `]', to match the opening `['.

Để biết thêm thông tin, bao gồm các thử nghiệm được hỗ trợ và cách chúng hoạt động, bạn sẽ phải xem trợ giúp test. Khi bạn chạy lệnh help test, bạn sẽ nhận được một danh sách chi tiết. Thay vì tái tạo tất cả, đây là phần về toán tử chuỗi:

      -z STRING      True if string is empty.

      -n STRING
         STRING      True if string is not empty.

      STRING1 = STRING2
                     True if the strings are equal.
      STRING1 != STRING2
                     True if the strings are not equal.
      STRING1 < STRING2
                     True if STRING1 sorts before STRING2 lexicographically.
      STRING1 > STRING2
                     True if STRING1 sorts after STRING2 lexicographically.

Lưu ý rằng -n STRINGvà chỉ cần STRINGlàm điều tương tự: họ kiểm tra nếu chuỗi STRINGkhông trống.


2
Giải thích tốt
Sergiy Kolodyazhnyy

1
Có lẽ cũng đề cập rằng điều này có hàm ý cho các biến không được trích dẫn không được đặt, như thế này: paste.ubfox.com/25831047
Sergiy Kolodyazhnyy

1
@SergiyKolodyazhnyy Tôi nghĩ rằng nó có thể tốt hơn trong một câu trả lời riêng biệt. Các biến không được đặt, hoặc được đặt nhưng trống hoặc chỉ chứa IFSkhoảng trắng sẽ làm điều đó; các biến có chứa nhiều từ thay vì 0 tạo ra hiệu ứng khác và có thể khiến một bài kiểm tra hoàn toàn khác được chạy. Các chuỗi xuất hiện theo nghĩa đen với mục đích là toán hạng sẽ chỉ hoạt động chính xác nếu chúng không chứa dấu cách hoặc tab hoặc nếu chúng được trích dẫn. Câu trả lời sẽ trở nên dài hơn và phức tạp hơn nếu tôi đề cập đến chủ đề này một cách dễ tiếp cận. Nếu bạn quyết định đăng câu trả lời, vui lòng gửi cho tôi ở đây về nó!
Eliah Kagan

@Eliah Kagan, câu trả lời của bạn đầy đủ và chi tiết hơn mặc dù câu trả lời của Ignacio Vazquez-Abrams đã trả lời câu hỏi của tôi.
Ravi Kumar

1
Tôi nghĩ rằng bạn đang thiếu lý do và phải theo cách này: nếu không, [ "$var" ]sẽ không bao giờ có thể sử dụng được như một bài kiểm tra vì $varcó thể mở rộng sang -n.
R ..

12

[ -n ]là đúng bởi vì [lệnh (còn gọi là testlệnh) hành động theo số lượng đối số được đưa ra. Nếu nó chỉ được đưa ra một đối số duy nhất, kết quả là "true" nếu đối số là một chuỗi không trống. "-N" là một chuỗi có 2 ký tự, không trống, do đó "đúng".

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.