it-swarm-vi.tech

Sự khác biệt giữa dấu ngoặc kép và dấu ngoặc đơn trong bash là gì?

Tôi chỉ tự hỏi chính xác sự khác biệt giữa

[[ $STRING != foo ]]

[ $STRING != foo ]

là, ngoài cái sau đó là tuân thủ posix, được tìm thấy trong sh và cái trước là một phần mở rộng được tìm thấy trong bash.

451
0x89

Có một số khác biệt. Theo tôi, một vài trong số quan trọng nhất là:

  1. [ Là một nội dung trong Bash và nhiều hệ vỏ hiện đại khác. Nội dung [ Tương tự như test với yêu cầu bổ sung về việc đóng ]. Các nội trang [test bắt chước chức năng /bin/[/bin/test Cùng với các giới hạn của chúng để các tập lệnh tương thích ngược. Các tệp thực thi ban đầu vẫn tồn tại chủ yếu để tuân thủ POSIX và tương thích ngược. Chạy lệnh type [ Trong Bash chỉ ra rằng [ Được hiểu là một nội trang theo mặc định. (Lưu ý: which [ Chỉ tìm kiếm các tệp thực thi trên đường dẫn và tương đương với type -p [)
  2. [[ Không tương thích, nó sẽ không nhất thiết hoạt động với bất cứ điều gì /bin/sh Trỏ đến. Vì vậy, [[ Là tùy chọn Bash/Zsh/Ksh hiện đại hơn.
  3. [[ Được tích hợp vào Shell và không có yêu cầu về di sản, bạn không cần phải lo lắng về việc tách Word dựa trên IFS biến để làm rối tung các biến đánh giá thành một chuỗi có khoảng trắng. Do đó, bạn không thực sự cần phải đặt biến trong dấu ngoặc kép.

Đối với hầu hết các phần, phần còn lại chỉ là một số cú pháp đẹp hơn. Để thấy nhiều sự khác biệt hơn, tôi khuyên bạn nên liên kết này với câu trả lời FAQ: Sự khác biệt giữa kiểm tra, [và [[? . Trên thực tế, nếu bạn nghiêm túc về kịch bản bash, tôi khuyên bạn nên đọc toàn bộ wiki , bao gồm Câu hỏi thường gặp, Cạm bẫy và Hướng dẫn . Phần kiểm tra từ phần hướng dẫn cũng giải thích những khác biệt này và tại sao (các) tác giả nghĩ rằng [[ Là lựa chọn tốt hơn nếu bạn không cần lo lắng về việc là di động. Những lý do chính là:

  1. Bạn không phải lo lắng về việc trích dẫn phía bên trái của bài kiểm tra để nó thực sự được đọc dưới dạng một biến.
  2. Bạn không phải thoát ít hơn và lớn hơn < > Với dấu gạch chéo ngược để chúng không bị đánh giá là chuyển hướng đầu vào, điều này thực sự có thể gây rối một số nội dung bằng cách ghi đè tệp. Điều này một lần nữa quay trở lại [[ Là một nội trang. Nếu [(test) là một chương trình bên ngoài, Shell sẽ phải tạo một ngoại lệ theo cách nó đánh giá <> Chỉ khi /bin/test Được gọi, sẽ không được gọi t thực sự có ý nghĩa.
325
Kyle Brandt

Nói ngắn gọn:

[là một bash Nội dung

[[]] là bash Từ khóa

Từ khóa: Từ khóa khá giống các nội trang, nhưng sự khác biệt chính là các quy tắc phân tích cú pháp đặc biệt áp dụng cho chúng. Ví dụ: [là một bash dựng sẵn, trong khi [[là một từ khóa bash. Cả hai đều được sử dụng để thử nghiệm công cụ, nhưng vì [[là một từ khóa chứ không phải là nội dung, nên nó được hưởng lợi từ một vài quy tắc phân tích cú pháp đặc biệt giúp việc này dễ dàng hơn nhiều:

  $ [ a < b ]
 -bash: b: No such file or directory
  $ [[ a < b ]]

Ví dụ đầu tiên trả về lỗi vì bash cố gắng chuyển hướng tệp b sang lệnh [a]. Ví dụ thứ hai thực sự làm những gì bạn mong đợi nó. Ký tự <không còn có ý nghĩa đặc biệt của toán tử Chuyển hướng tệp.

Nguồn: http://mywiki.wooledge.org/BashGuide/CommandsAndArgument

138
abhiomkar

Khác biệt về hành vi

Một số khác biệt về Bash 4.3.11:

  • Gia hạn POSIX vs Bash:

  • lệnh thường xuyên vs ma thuật

    • [ Chỉ là một lệnh thông thường có tên lạ.

      ] Chỉ là một đối số của [ Ngăn các đối số tiếp theo được sử dụng.

      Ubuntu 16.04 thực sự có một tệp thực thi cho nó tại /usr/bin/[ Được cung cấp bởi coreutils, nhưng phiên bản tích hợp bash được ưu tiên.

      Không có gì được thay đổi theo cách Bash phân tích lệnh.

      Cụ thể, < Là chuyển hướng, &&|| Ghép nhiều lệnh, ( ) Tạo các chuỗi con trừ khi thoát khỏi \ Và mở rộng Word xảy ra như bình thường.

    • [[ X ]] Là một cấu trúc đơn làm cho X được phân tích cú pháp một cách kỳ diệu. <, &&, ||() Được xử lý đặc biệt và quy tắc chia tách từ khác nhau.

      Ngoài ra còn có sự khác biệt hơn nữa như ==~.

      Trong Bashese: [ Là một lệnh tích hợp và [[ Là một từ khóa: https://askubfox.com/questions/445749/whats-the- sự khác biệt giữa Shell-buildin-và-Shell-keyword

  • <

  • &&||

    • [[ a = a && b = b ]]: Đúng, logic
    • [ a = a && b = b ]: Lỗi cú pháp, && Được phân tích cú pháp dưới dạng dấu tách lệnh AND cmd1 && cmd2
    • [ a = a -a b = b ]: Tương đương, nhưng không được chấp nhận bởi POSIX³
    • [ a = a ] && [ b = b ]: POSIX và tương đương đáng tin cậy
  • (

    • [[ (a = a || a = b) && a = b ]]: sai
    • [ ( a = a ) ]: lỗi cú pháp, () được hiểu là một nhánh con
    • [ \( a = a -o a = b \) -a a = b ]: tương đương, nhưng () không được chấp nhận bởi POSIX
    • { [ a = a ] || [ a = b ]; } && [ a = b ] Tương đương POSIX5
  • Chia tách từ và tạo tên tệp khi mở rộng (split + global)

    • x='a b'; [[ $x = 'a b' ]]: Đúng, không cần trích dẫn
    • x='a b'; [ $x = 'a b' ]: Lỗi cú pháp, mở rộng thành [ a b = 'a b' ]
    • x='*'; [ $x = 'a b' ]: Lỗi cú pháp nếu có nhiều hơn một tệp trong thư mục hiện tại.
    • x='a b'; [ "$x" = 'a b' ]: Tương đương POSIX
  • =

    • [[ ab = a? ]]: Đúng, vì nó phù hợp với mẫu (* ? [ Là ma thuật). Không toàn cầu mở rộng để tập tin trong thư mục hiện tại.
    • [ ab = a? ]: a? Toàn cầu mở rộng. Vì vậy, có thể đúng hoặc sai tùy thuộc vào các tệp trong thư mục hiện tại.
    • [ ab = a\? ]: Sai, không phải mở rộng toàn cầu
    • === Giống nhau ở cả [[[, Nhưng == Là tiện ích mở rộng Bash.
    • case ab in (a?) echo match; esac: Tương đương POSIX
    • [[ ab =~ 'ab?' ]]: Sai4, mất phép thuật với ''
    • [[ ab? =~ 'ab?' ]]: Đúng
  • =~

    • [[ ab =~ ab? ]]: True, POSIX kết hợp biểu thức chính quy mở rộng , ? Không mở rộng toàn cầu
    • [ a =~ a ]: Lỗi cú pháp. Không có bash tương đương.
    • printf 'ab\n' | grep -Eq 'ab?': Tương đương POSIX (chỉ dữ liệu một dòng)
    • awk 'BEGIN{exit !(ARGV[1] ~ ARGV[2])}' ab 'ab?': POSIX tương đương.

Khuyến nghị : luôn sử dụng [].

Có tương đương POSIX cho mỗi cấu trúc [[ ]] Tôi đã thấy.

Nếu bạn sử dụng [[ ]], Bạn:

  • mất tính di động
  • buộc người đọc phải tìm hiểu sự phức tạp của một phần mở rộng bash khác. [ Chỉ là một lệnh thông thường có tên lạ, không có ngữ nghĩa đặc biệt nào được tham gia.

Lấy cảm hứng từ cấu trúc [[...]] Tương đương trong Korn Shell

² nhưng không thành công đối với một số giá trị của a hoặc b (như + Hoặc index) và so sánh số nếu ab trông giống như số nguyên thập phân. expr "x$a" '<' "x$b" Hoạt động xung quanh cả hai.

Và cũng không thành công đối với một số giá trị của a hoặc b như ! Hoặc (.

4 trong bash 3.2 trở lên và cung cấp khả năng tương thích với bash 3.1 không được bật (như với BASH_COMPAT=3.1)

5 mặc dù việc nhóm (ở đây với nhóm lệnh {...;} thay vì (...) sẽ chạy một chuỗi con không cần thiết) là không cần thiết vì các toán tử Shell ||&& (trái ngược với các toán tử ||&&[[...]] hoặc toán tử -o/-a[) bằng nhau quyền ưu tiên. Vì vậy, [ a = a ] || [ a = b ] && [ a = b ] Sẽ tương đương.

Giá đỡ đơn tức là [] là POSIX Shell tuân thủ để kèm theo biểu thức điều kiện.

Chân đế đôi tức là [[]] là phiên bản nâng cao (hoặc mở rộng) của phiên bản POSIX tiêu chuẩn, phiên bản này được hỗ trợ bởi bash và các shell khác (zsh, ksh).

Trong bash, để so sánh số, chúng tôi sử dụng eq, ne, ltgt, với dấu ngoặc kép để so sánh, chúng tôi có thể sử dụng ==, !=, <,> theo nghĩa đen.

  • [ là một từ đồng nghĩa với lệnh kiểm tra. Ngay cả khi nó được tích hợp vào Shell, nó sẽ tạo ra một quy trình mới.
  • [[ là phiên bản cải tiến mới của nó, là một từ khóa, không phải là một chương trình.

ví dụ:

[ var1 lt var2] #works
[ var1 < var2] #error: var2 No such file or directory 
[ var1 \< var2] #works with escape
[[ var1 < var2]] #works
6
Premraj

Dựa trên việc đọc nhanh các phần có liên quan của trang, sự khác biệt chính dường như là các toán tử ==!= Khớp với một mẫu, thay vì một chuỗi bằng chữ và cũng có toán tử so sánh regex =~.

4
womble