文字列にダッシュまたはグレーの部分文字列が含まれているかどうかを確認するには?

文字列にダッシュまたはグレーの部分文字列が含まれているかどうかを確認するには?

これが私が試していることです:

#!/bin/sh
contains() {
    if $(echo $1 | grep -c $2) ; then
        echo "0" # contains
    else
        echo "1" # not contains
    fi
}

myString=$1
mySubsting=$2

contains $myString '$mySubsting'

実行例は次のとおりです。

# sh ./myScript abcdef bc
./myTest: line 3: 0: command not found
1

編集する:

元の質問:Bourne Shellで文字列に部分文字列が含まれているかどうかを確認する方法は?

これが私が試していることです:

  #!/bin/sh
  if echo $1 | grep -q $2
  then
    echo "0"
  else
    echo "1"
  fi

実行例は次のとおりです。

$ sh ./myTest "$(systemctl status ntp)" "Active: active"
grep: active: No such file or directory
1

文字列に他の文字列が含まれているかどうかを正しく確認するには?

答え1

関数を含む移植可能な(dash、bash、kshなど)スクリプト:

#!/bin/sh

contains() {  if    [ "$1" ] &&            # Is there a source string.
                    [ "$2" ] &&            # Is there a substring.
                    [ -z "${1##*"$2"*}" ]; # Test substring in source.
              then  echo 0;                # Print a "0" for a match.
              else  echo 1;                # Print a "1" if no match.
              fi;
            }

contains "$1" "$2"

ここで、0 は「含む」(真値)を意味します。

これは次のようにテストされます。

 $ contains "test a simple line" simpl
 1

 $ contains "One sentence" "No more"
 0

答え2

Bourneシェルにはこの目的のための設定があります。これは現代のものと同じですsh(これはBourneシェルでサポートされていない使用中のものと似ています$(...)。Bourneシェルの場合は他のエラーが発生します)。

case $1 in
  *"$2"*) printf '"%s" is in "%s"\n' "$2" "$1"
esac

を使用する場合は、grep次のようになります。

if printf '%s\n' "$1" | grep -Fqe "$2"; then
  printf '"%s" is in "%s"\n' "$2" "$1"
fi

または

if grep -Fqe "$2" << EOF
$1
EOF
then
  printf '"%s" is in "%s"\n' "$2" "$1"
fi

$2ただし、改行文字が含まれていない場合にのみ正常に動作します。

それにもかかわらず、ほとんどのパラメータ拡張を引用する必要があります。必要ない唯一のところはあの上ですが、case $1それでもcase "$1"病気ではありません。

コードに関するいくつかの注意:

  1. echo任意の文字列と一緒に使用することはできません。。ここでは、実装によって、echoまたは同じ値に対して失敗します。$1-nfoo\bar
  2. シェルで引用されていないパラメータ拡張は非常に特別な意味を持ちます。。あなたはそうしたくありません。たとえば、grep -c $2または同じ値を試してみてください。$2*root /etc/passwd
  3. grepなしでは、-F正規表現の一致に使用されます。-F文字列(サブ文字列)検索(過去)を変更する必要がありますfgrepが、$2複数行が含まれている場合は再grep -F検索する場合どの入力では、これらの行の内容は文字列ではなくorをgrep -F $'a\nb'探します。ab$'a\nb'
  4. grep -c $2始まると、内容は$2オプションとして扱われます-。あなたはこの状況を望むgrep -c -e "$2"grep -c -- "$2"避けます。
  5. ブール条件を報告するために標準出力の代わりに終了状態を使用しようとしています。スクリプトではexitexit 0trueの場合exit 1(またはゼロ以外の数字、120より大きい値を避ける)の場合はfalse)を使用します。機能の場合はreturn代わりに使用してください。スクリプトと関数の両方が最後のコマンド実行状態を返します。
  6. $(cmd) 拡大する末尾の改行を引いた出力cmd(そして引用符が再び欠けて、ここで分割+globを経ること)です。したがって、cmd出力がに拡張される0\nと、runはというコマンドを実行しようとします。出力を終了状態に変換するには(ブール値として使用可能)、終了コードで出力として終了するサブシェルが起動します。$(cmd)0$(cmd)0cmd(exit "$(cmd)")cmd
  7. grep -c発生回数を計算します。ここでは、総数は必要なく、検索されたか(一致する項目が 1 つ以上あるか)を知るだけです。grep -q見つかったら検索を停止するので、これはより効率的です。grep(標準)オプションをサポートしていない以前の-q実装では、最初の一致で停止しますが、ファイル名を出力するfgrep -le "$2" > /dev/null.forを使用できます(ここでは出力をリダイレクトして削除します)。-lfgrep/dev/null

答え3

Bashはデフォルトでこれをサポートしています。

$ string1="abcmoocow"
$ string2="moo"
$ if [[ $string1 == *$string2* ]]; then echo "Match"; else echo "No Match"; fi
Match
$ string1="abccrowcow"
$ if [[ $string1 == *$string2* ]]; then echo "Match"; else echo "No Match"; fi
No Match

また、あなたの例を修正してください。

if $(echo $1 | grep -c $2) ; then

になる:

if [ -n "$(echo $1 | grep -c $2)" ]; then

(grep がデータを返すことを確認)

また、終了コードも使用できます。

$ echo bob | grep "o" &>/dev/null; echo $?
0
$ echo bob | grep "z" &>/dev/null; echo $?
1

関連情報