リストの項目が期待どおりに機能しないことを確認する Bash

リストの項目が期待どおりに機能しないことを確認する Bash

以下に基づく条件を持つスクリプトを作成しようとしています。変数がリストに表示されます:

#!/bin/bash

LIST=`ls`

function listcontains() {
    [[ $1 =~ (^|[[:space:]])$2($|[[:space:]]) ]] && return 0 || return 1
}

if [ $(listcontains "${LIST}" "multi.sh") ] ; then
     echo "Found!"
else
    echo "Failed :("
fi

$(listcontains "${LIST}" "multi.sh")
echo returned $?

リストには「multi.sh」というファイルがあるため、「Found!」が予想されますが、上記のスクリプトでは「Failed:(」を報告します。後続の呼び出しは0を返します。

頑張った

if [ 0 -eq $(listcontains "${LIST}" "multi.sh") ] ; then

ところで、エラーが発生します。

./script.sh: 行9: [: 0: 単項演算子が必要

失敗:(

私がここで何を見逃しているのでしょうか?

ベストアンサー1

if [ $(listcontains "${LIST}" "multi.sh") ] ; then

関数は何も印刷しないので、コマンド置換はトークン化後にフィールドを生成しません。これは実行と同じで、if [ ]; then ...間にパラメータがない場合はfalse状態を返します。[][

引用符を使用してこれを行うと、空の文字列をlikeif [ "$(listcontains...)" ]; thenに渡し、false状態も返すので役に立ちません。 (括弧の間にパラメータがあり、そのパラメータがnullでないことを確認してください。)[[ "" ]

コマンド置換自体の終了ステータスは、実行する他のコマンドがない場合にのみ表示されます。$(listcontains ...)これは、後で1行でコマンドを単独で実行する場合です。

コマンドオーバーライドでテストするには、何かを印刷する必要があります。例えば

listcontains() {
    if ...; then
        echo yes
    fi # else print nothing
}
if [ "$(listcontains ...)" ]; then
    echo ok
fi

(またはと共にif [ "$(listcontains ...)" = yes ]; then ...

ただし、終了ステータスを直接表示できるため、これは必要ありません。

listcontains() {
    if [[ ... ]]; then
        return 0
    fi
    return 1
}
if listcontains ...; then
    echo ok
fi

関数の終了状態は最後のコマンドの終了状態なので、関数を次のように単純化できます。

listcontains() {
    [[ $1 =~ (^|[[:space:]])$2($|[[:space:]]) ]]
}

$2ただし、内容に正規表現の特殊文字が含まれていても、内容が文字通り処理されるように引用したいと思います。

たとえば、上記の場合は単一の文字と一致するため、listcontains 'foo matchxsh bar' match.sh一致が検索されます。.一致しない括弧などの問題が発生する可能性があります。

一致する前に文字列の先頭と末尾にスペースを入れることで長さを短くすることもできます。

listcontains() {
    [[ " $1 " =~ [[:space:]]"$2"[[:space:]] ]]
}

または、より多くのPOSIXlyを使用してDashでも使用できます。

listcontains() {
    case " $1 " in
        *[[:space:]]"$2"[[:space:]]*) return 0;;
        *) return 1;;
    esac
}

おすすめ記事