So sánh các số nguyên: biểu thức số học hoặc biểu thức điều kiện


20

Trong Bash, hai số nguyên có thể được so sánh bằng biểu thức điều kiện

arg1 OP arg2

OP là một trong những -eq, -ne, -lt, -le, -gt, hoặc -ge. Các toán tử nhị phân số học này trả về true nếu arg1 bằng, không bằng, nhỏ hơn, nhỏ hơn hoặc bằng, lớn hơn hoặc lớn hơn hoặc bằng arg2 , tương ứng. Arg1arg2 có thể là số nguyên dương hoặc âm.

hoặc biểu thức số học:

<= >= < > so sánh

== != bình đẳng và bất bình đẳng

Tại sao chúng ta có hai cách khác nhau để so sánh hai số nguyên? Khi nào nên sử dụng?

Ví dụ: [[ 3 -lt 2 ]]sử dụng biểu thức điều kiện và (( 3 < 2 ))sử dụng biểu thức số học. Cả hai trả về 0 khi so sánh là đúng

Khi so sánh hai số nguyên, hai phương thức này có thể luôn được sử dụng thay thế cho nhau không? Nếu có, tại sao Bash có hai phương thức chứ không phải một?


1
= != < <= > >=so sánh chuỗi . 1 -eq 01nhưng 1 != 018 -lt 42nhưng8 > 42
dave_thndry_085

Chúng bị quá tải trong các biểu thức số học.
Tim

1
bạn sẽ phải tìm kiếm trong các thay đổi bash để tìm hiểu khi mỗi tính năng được thêm vào. Tôi nghi ngờ các biểu thức số học được thêm vào muộn hơn nhiều so với lệnh kiểm tra.
glenn jackman

Tôi không hỏi về việc so sánh các chuỗi. @muru.
Tim

Câu trả lời:


28

Vâng, chúng tôi có hai cách khác nhau để so sánh hai số nguyên.

Dường như những sự thật này không được chấp nhận rộng rãi trong diễn đàn này:

  1. Bên trong thành ngữ [ ]các nhà khai thác để so sánh số học là -eq, -ne, -lt, -le, -gt-ge.

    Vì chúng cũng nằm trong một lệnh kiểm tra và bên trong a [[ ]].

    Có bên trong thành ngữ này, =, <, vv là các nhà khai thác chuỗi.

  2. Bên trong thành ngữ (( ))các nhà khai thác để so sánh số học là ==, !=, <, <=, >, và >=.

    Không, đây không phải là "Mở rộng số học" (bắt đầu bằng a $) như $(( )). Nó được định nghĩa là "Lệnh tổng hợp" trong bash man.

    Có, nó tuân theo các quy tắc tương tự (nội bộ) của "Mở rộng số học" nhưng không có đầu ra, chỉ có một giá trị thoát. Nó có thể được sử dụng như thế này:

if (( 2 > 1 )); then ...

Tại sao chúng ta có hai cách khác nhau để so sánh hai số nguyên?

Tôi đoán rằng cái sau (( ))được phát triển như một cách đơn giản hơn để thực hiện các bài kiểm tra số học. Nó gần giống như $(( ))nhưng không có đầu ra.

Tại sao hai? Vâng giống như lý do tại sao chúng ta có hai printf(bên ngoài và dựng sẵn) hoặc bốn thử nghiệm (bên ngoài test, được xây dựng trong test, [[[). Đó là cách mà vỏ sò phát triển, cải thiện một số khu vực trong một năm, cải thiện một số khác trong năm tới.

Khi nào nên sử dụng?

Đó là một câu hỏi rất khó vì không có sự khác biệt hiệu quả. Tất nhiên có một số khác biệt trong cách [ ]làm việc và (( ))công việc trong nội bộ, nhưng: cái nào tốt hơn để so sánh hai số nguyên? Bất kỳ ai!.

Khi so sánh hai số nguyên, hai phương thức này có thể luôn được sử dụng thay thế cho nhau không?

Đối với hai số tôi buộc phải nói có.
Nhưng đối với các biến, mở rộng, các phép toán có thể có những khác biệt chính cần có lợi cho cái này hay cái khác. Tôi không thể nói rằng hoàn toàn cả hai đều bằng nhau. Đối với một, (( ))có thể thực hiện một số hoạt động toán học theo trình tự:

if (( a=1, b=2, c=a+b*b )); then echo "$c"; fi

Nếu có, tại sao Bash có hai phương thức chứ không phải một?

Nếu cả hai đều hữu ích, tại sao không?


1
=là một bài tập và ==là một so sánh trong mở rộng số học. Câu hỏi trích dẫn chính xác. Nhưng câu trả lời là sai.
ceving

12

Trong lịch sử, testlệnh tồn tại đầu tiên (ít nhất là từ phiên bản thứ bảy Unix năm 1979). Nó sử dụng các nhà khai thác =!=để so sánh chuỗi, và -eq, -ne, -lt, vv để so sánh những con số. Ví dụ, test 0 = 00là sai, nhưng test 0 -eq 00là đúng. Tôi không biết tại sao cú pháp này được chọn, nhưng nó có thể tránh sử dụng <>, cái vỏ sẽ được phân tích cú pháp như các toán tử chuyển hướng. Các testlệnh có cú pháp khác một vài năm sau đó: [ … ]tương đương với test ….

Các [[ … ]]cú pháp có điều kiện, bên trong đó <>có thể được sử dụng như các nhà khai thác mà không cần trích dẫn, đã được bổ sung sau, trong ksh. Nó giữ khả năng tương thích ngược với [ … ], vì vậy nó đã sử dụng cùng các toán tử, nhưng được thêm vào <>để so sánh các chuỗi (ví dụ, [[ 9 > 10 ]]nhưng [[ 9 -lt 10 ]]). Để biết thêm thông tin, hãy xem sử dụng dấu ngoặc đơn hoặc dấu ngoặc kép - bash

Các biểu thức số học cũng đến muộn hơn so với testlệnh, trong vỏ Korn , tại một số thời điểm trong những năm 1980. Họ theo cú pháp của ngôn ngữ C, rất phổ biến trong các vòng tròn Unix. Do đó, họ đã sử dụng các toán tử C: ==cho đẳng thức, <=cho ít hoặc bằng, v.v.

Phiên bản thứ bảy của Unix không có biểu thức số học, nhưng nó có exprlệnh , cũng đã thực hiện cú pháp giống như C cho các hoạt động số nguyên, bao gồm các toán tử so sánh của nó. Trong một kịch bản shell, các ký tự <>phải được trích dẫn để bảo vệ chúng khỏi shell, ví dụ như if expr 1 \< 2; …tương đương với if test 1 -lt 2; …. Việc bổ sung các biểu thức số học vào hệ vỏ khiến hầu hết các cách sử dụng exprbị lỗi thời, vì vậy ngày nay nó không được biết đến nhiều.

Trong tập lệnh sh, bạn thường sử dụng các biểu thức số học để tính giá trị nguyên và [ … ]để so sánh các số nguyên.

if [ "$((x + y))" -lt "$z" ]; then 

Trong tập lệnh ksh, bash hoặc zsh, bạn có thể sử dụng ((…))cho cả hai.

if ((x + y < z)); then 

Biểu [[ … ]]mẫu rất hữu ích nếu bạn muốn sử dụng các điều kiện liên quan đến những thứ khác ngoài số nguyên.


1

Theo trang man test, = và! = Được sử dụng để so sánh chuỗi trong khi các biểu thức -eq, -gt, -lt, -ge, -le và -ne là so sánh số nguyên. Tôi đã luôn tuân theo quy ước này khi viết kịch bản shell và nó luôn hoạt động. Xin lưu ý rằng nếu bạn có các biến trong biểu thức, bạn có thể cần trích dẫn các biến theo một cách nào đó để tránh thực hiện so sánh null.

Trên giấy, chúng tôi thực hiện so sánh chuỗi / số mà không cần suy nghĩ nhiều. Mặt khác, một máy tính không biết liệu 987 là một số hay một chuỗi ký tự. Bạn cần các toán tử khác nhau để báo cho máy tính biết phải làm gì để bạn có được kết quả đúng. Có một số thông tin bổ sung ở đây giải thích một số lịch sử. Về cơ bản, các biến được tháo gỡ và vẫn theo cách đó để tương thích lịch sử.


Trong bài viết của tôi, = !=là các toán tử số học, trong khi trang chủ củatest chỉ hiển thị các toán tử biểu thức điều kiện.
Tim
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.