web-dev-qa-db-ja.com

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

これが私が大事にしているものです:

#!/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

ある文字列に別の文字列が含まれているかどうかを適切に確認するにはどうすればよいですか?

3
Oleksandr

ボーンシェルにはそのための構造がありました。これは、最近のshと同じです(これは、使用しているものに似ていますが、Bourne Shellは$(...)をサポートしていませんでした。BourneShellの場合は、別のエラー):

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-nなどのfoo\barの値に対して失敗します。
  2. パラメータ展開を引用符で囲まないでおくと、シェルでは非常に特別な意味があります 。あなたはそれをしたくありません。たとえば、grep -c $2または$2のような*の値を持つroot /etc/passwdを試してください。
  3. -Fなしのgrepは、正規表現照合用です。固定文字列(部分文字列)の検索には-Fが必要です(以前はfgrepで使用されていました)が、$2に複数の行が含まれている場合、grep -Fにそれらの内容のanyを検索するように指示します入力の行(grep -F $'a\nb'$'a\nb'文字列ではなくaまたはbを検索します)。
  4. grep -c $2では、$2で始まっている場合、-の内容はオプションとして扱われます。 grep -c -e "$2"またはgrep -c -- "$2"でそれを回避する必要があります。
  5. ブール条件を報告するために、標準出力ではなく終了ステータスを使用したい。 exit(trueの場合はexit 0、falseの場合はexit 1(または0以外の数値。ただし、120より大きい値は避けてください)を含むスクリプトでは、falseの場合)。関数の場合は、代わりにreturnを使用します。ただし、スクリプトと関数の両方が、最後に実行されたコマンドのステータスで返されます。
  6. $(cmd)expandscmdの出力(および引用符がないため、ここでsplit + globが実行されます)から末尾の改行文字を差し引いたもの。したがって、cmd0\nを出力する場合、$(cmd)0に展開されます。したがって、$(cmd)を実行すると、0というコマンドを実行しようとします。 cmdの出力を終了ステータスに変換する(ブール値として使用できるようにする)には、(exit "$(cmd)")が必要です。これにより、cmdの出力を終了コードとして終了するサブシェルが開始されます)。
  7. grep -cは、発生回数をカウントします。ここでは、完全な数を取得する必要はありません。それが見つかったかどうか(少なくとも1つの一致がある場合)を知るだけで済みます。そのため、grep -qは、検索後に検索を停止するため、より効率的です。 (標準の)-qオプションをサポートしない古いgrep実装では、fgrep -le "$2" > /dev/nullを使用できます。 -lを使用すると、fgrepも最初の一致で停止しますが、ファイル名を出力します(ここでは、出力を/dev/nullにリダイレクトして破棄します)。
7

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
1
mikejonesey

関数のポータブル(ダッシュ、バッシュ、kshなど)ソリューションは次のとおりです。

contains(){if ["$ {1 ## " $ 2 "}"];次に0をエコーし​​ます。それ以外の場合は1をエコーし​​ます。 #0は含む

0
Isaac