2009-07-07 49 views
22

Tôi đang cố gắng so sánh hai chuỗi trong một tập lệnh shell đơn giản. Tôi đã sử dụng /bin/sh thay vì /bin/bash, và sau không biết bao nhiêu giờ gỡ lỗi, nó quay ra sh (mà thực sự là dấu gạch ngang) không thể xử lý khối mã này:bash, gạch ngang và so sánh chuỗi

if [ "$var" == "string" ] 
then 
    do something 
fi 

một cách cầm tay để so sánh chuỗi là gì sử dụng /bin/sh? Tôi biết tôi luôn luôn có thể làm điều ngược lại bằng cách sử dụng! =, Nhưng tôi đang tự hỏi về một cách sạch hơn, di động.

+2

Bạn có thể sử dụng '[[$ var ==" string "]]', là POSIX, nhưng tùy chọn (afaik). Hoặc bạn sử dụng '[" $ var "=" string "]'. Lưu ý '" "' xung quanh biến trong phiên bản dấu ngoặc đơn: nó được yêu cầu trong trường hợp '$ var' là trống –

+0

Phần quan trọng là dấu ngoặc kép quanh' $ var' như đã được đề cập. Không có dấu ngoặc kép, '[$ var =" value "]' trở thành '[=" value "]' gây nhầm lẫn cho shell khá khủng khiếp. Có thể bạn sẽ thấy một lỗi như _ "[: =: unary operator expected" _ khi bạn gặp phải một biến trống. –

+0

Tôi hiểu về "$ var" so với $ var, vấn đề của tôi là == vs. = – LiraNuna

Trả lời

32

dash là một vỏ POSIX rất nghiêm ngặt, nếu nó hoạt động trong dash, nó gần như chắc chắn nó sẽ hoạt động trong vỏ POSIX khác.

Hãy thử:

if [ "$var" = "string" ] 
then 
    some_command 
fi 
8

Tại sao thậm chí có khả năng tập lệnh của bạn sẽ được chạy bởi trình bao "sai"? Tôi nghĩ rằng bạn có thể làm điều đó một điều kiện tiên quyết của sản phẩm của bạn bằng cách sử dụng các tiêu chuẩn dòng sh-bang ở phía trên cùng của kịch bản của bạn:

#!/bin/bash 

Thậm chí nếu người dùng sử dụng một lớp vỏ khác nhau, các tiện ích khác nói chung vẫn còn đó, và nếu không, chỉ đơn giản là khiếu nại và nói rằng họ là một req req.

Chính xác giống như cách một mức hạt nhân cụ thể hoặc sự tồn tại của awk, có thể là yêu cầu trước đó.

Đối với câu hỏi cụ thể của bạn, tôi tin rằng cả hai shbash cho phép đơn '=' sẽ được sử dụng để so sánh chuỗi - đó là POSIX hành vi:

if [ "a" = "a" ] ; then 
    echo yes 
fi 

yes 
+1

* "Tại sao thậm chí có khả năng kịch bản của bạn sẽ được chạy bởi" sai "shell?" * - Có thể kiểm soát vỏ nào được sử dụng bởi Autoconf không? (Đó là lý do tôi đang tìm kiếm câu trả lời) – jww

3

Sử dụng = thay vì ==. So sánh được xử lý bằng kiểm tra (1). /usr/bin/[ thường là một liên kết đến /usr/bin/test. Điểm khác biệt duy nhất là nếu bạn sử dụng [ trong tập lệnh trình bao, yêu cầu ] cũng vậy.

Lưu ý rằng bash có tích hợp test/[, vì vậy nó không thực sự sử dụng /usr/bin/test.

-3

bạn có thể sử dụng awk

awk 'BEGIN{ 
string1="test" 
string2="tes1t" 
if(s1==s2){ 
    print "same string" 
}else{ 
    print "not same" 
} 
}' 
1

Những câu trả lời đã được đăng chắc chắn đúng, nhưng nó có thể là giá trị cần lưu ý rằng việc mở rộng thỉnh thoảng tham số có thể phục vụ cùng một mục đích với lẽ một số tính linh hoạt bổ sung.

% p() { printf 'notvar = %b\n' "${notvar##"${string1}"}${string2}" ; } 
% string1='some stuff about things\c' 
% string2='some different stuff maybe' 
% notvar="$string1" p 
> 'some different stuff maybe' 
% notvar="$string2" p 
> 'some stuff about things' 

Ok, vì vậy ở trên là không siêu hữu ích như là, mà còn xem xét mà bạn có thể sử dụng phương pháp tương tự cho các biến thử nghiệm ở đây-tài liệu, in-line tập biến nếu cần thiết (ở một mức độ ...), hoặc thậm chí chỉ là một phương thức ngắn hơn (và nhanh hơn!) để viết câu lệnh đầu tiên của bạn.

[ ! "${var##"string"}" ] && _MATCH || _NOMATCH 

Hoặc thậm chí ...

[ ${#var#*"${s=string}"} -lt ${#var} ] && _SUB_STRING_TEST=TRUE 

Có thể thậm chí ...

% p() { printf '%s is %s of %s' "$2" "${var_chk-not}" "$1" 
> }<<HEREDOC 
> ${in="${1##*"${2}"*}"} 
> ${in:- 
>  ${in="${1##"${2}"}"} 
>  ${in:-${var_chk=all} 
>  ${var_chk=some} 
> } 
> HEREDOC 
% 
+1

Không chắc chắn tôi thấy lợi ích to lớn của những kỹ thuật này trừ khi bạn đang cố gắng để giành chiến thắng một cuộc thi obfuscation. – swdev

Các vấn đề liên quan