web-dev-qa-db-ja.com

bash、dash、stringの比較

単純なシェルスクリプトで2つの文字列を比較しようとしています。私は/bin/shの代わりに/bin/bashを使用していましたが、数え切れないほどのデバッグ時間の後、sh(実際にはダッシュです)はこのコードブロックを処理できないことがわかります。

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

/bin/shを使用して文字列を比較するポータブルな方法は何ですか?私は!=を使用して常に反対のことができることを知っていますが、よりクリーンでポータブルな方法について疑問に思っています。

29
LiraNuna

dashは非常に厳密なPOSIXシェルです。dashで動作する場合、他のPOSIXシェルでも動作することはほぼ確実です。

試してください:

if [ "$var" = "string" ]
then
    some_command
fi
45
J-16 SDiZ

スクリプトが「間違った」シェルによって実行される可能性さえあるのはなぜですか?スクリプトの上部にある標準のsh-bang行を使用して、製品の必須条件にすることができると思います。

#!/bin/bash

ユーザーが別のシェルsesを使用している場合でも、他のシェルは通常はまだ存在し、そうでない場合は、単に不満を示して前提条件であることを述べます。

特定のカーネルレベルまたはawkの存在が前提条件になることができるのとまったく同じ方法。

あなたの特定の質問については、shbashの両方で、単一の '='を文字列比較に使用できると考えています。つまり、POSIXの動作です。

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

yes
9
paxdiablo

=の代わりに==を使用してください。比較はtest(1)によって処理されます。 /usr/bin/[は通常、/usr/bin/testへのリンクです。唯一の違いは、シェルスクリプトで[を使用する場合、]も必要であることです。

Bashにはtest/[が組み込まれているため、実際には/usr/bin/testを使用しないことに注意してください。

3
skoob

すでに投稿されている答えは確かに正しいですが、場合によっては、パラメーターの拡張が同じ目的を果たし、おそらくいくつかの追加の柔軟性が得られることに注意することは価値があります。

% 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'

わかりましたので、上記はそのままではあまり役に立ちませんが、同様の方法を使用して、ヒアドキュメントの変数をテストしたり、必要に応じてインライン変数の割り当て(ある程度)をテストしたり、さらには短い(そして速い!)と同じように、最初のステートメントを記述します。

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

あるいは...

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

たぶん...

% 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
mikeserv