文字列がbashの別の部分文字列であるかどうかを判断する方法は?


49

文字列が別の文字列の一部の中にあるかどうかを確認したい。
例えば:

'ab' in 'abc' -> true
'ab' in 'bcd' -> false

bashスクリプトの条件でこれを行うにはどうすればよいですか?

回答:


27

より大きな文字列を含み、検索しようとしている部分文字列 ${VAR/subs}であるフォームを使用できます。VARsubs

my_string=abc
substring=ab
if [ "${my_string/$substring}" = "$my_string" ] ; then
  echo "${substring} is not in ${my_string}"
else
  echo "${substring} was found in ${my_string}"
fi

これ${VAR/subs}は、特に$VAR文字列の最初の出現がsubs削除されているため、特に$VAR単語が含まれていない場合はsubs変更されないため、機能します。


echoステートメントの順序を変更する必要があると思います。私が得たからab is not in abc
ルシオ

あなたが正しいです!:P
エドウィン

うーん、スクリプトは間違っています。そのように私は得るab was found in abcが、私が使用する場合、私はsubstring=z得るz was found in abc
ルシオ

1
今私は得るab is not in abc。しかしz was found in abc。これは面白いです:D
ルシオ

1
ああ!エコーはこの最初の瞬間にありました!XD-
エドウィン

47

[[ "bcd" =~ "ab" ]]
[[ "abc" =~ "ab" ]]

ブラケットはテスト用であり、二重ブラケットであるため、などの追加のテストが可能=~です。

したがって、このフォームを次のように使用できます

var1="ab"
var2="bcd"
if [[ "$var2" =~ "$var1" ]]; then
    echo "pass"
else
    echo "fail"
fi

編集:「=〜」を修正し、反転しました。


1
failこのパラメーターを使用して取得しますvar2="abcd"
ルシオ

3
@Lucio正しいのは[[ $string =~ $substring ]]です。答えを更新しました。
エリックカルヴァ


10

次の2つのアプローチは、bashだけでなく、POSIX互換環境で動作します。

substr=ab
for s in abc bcd; do
    if case ${s} in *"${substr}"*) true;; *) false;; esac; then
        printf %s\\n "'${s}' contains '${substr}'"
    else
        printf %s\\n "'${s}' does not contain '${substr}'"
    fi
done
substr=ab
for s in abc bcd; do
    if printf %s\\n "${s}" | grep -qF "${substr}"; then
        printf %s\\n "'${s}' contains '${substr}'"
    else
        printf %s\\n "'${s}' does not contain '${substr}'"
    fi
done

上記の出力の両方:

'abc' contains 'ab'
'bcd' does not contain 'ab'

前者には、別のgrepプロセスを生成しないという利点があります。

バックスラッシュが含まれている場合はマングルする可能性がprintf %s\\n "${foo}"あるecho "${foo}"ため、代わりに使用することに注意してください。echo${foo}


最初のバージョンxrandrは、変数に格納されているモニター名のリストでモニター名のサブストリングを見つけるのに最適です。+1と1K担当クラブへようこそ:)
WinEunuuchs2Unix

6

シェルケースステートメント

これは最もポータブルなソリューションであり、古いBourneシェルとKornシェルでも動作します

#!/bin/bash
case "abcd" in
    *$1*) echo "It's a substring" ;;
    *) echo "Not a substring" ;;
esac

サンプル実行:

$ ./case_substr.sh "ab"                                                                                           
It's a substring
$ ./case_substr.sh "whatever"                                                                                     
Not a substring

echoを使用してexit 1exit 0成功または失敗を示すために使用できる具体的に使用する必要はないことに注意してください。

同様にできることは、特定の戻り値(一致する場合は0、一致しない場合は1)を持つ関数(必要に応じて大きなスクリプトで使用できる)を作成することです。

$ ./substring_function.sh                                  
ab is substring

$ cat substring_function.sh                                
#!/bin/sh

is_substring(){
    case "$2" in
        *$1*) return 0;;
        *) return 1;;
    esac
}

main(){
   if is_substring "ab" "abcdefg"
   then
       echo "ab is substring"
   fi
}

main $@

grep

$ grep -q 'ab' <<< "abcd" && echo "it's a substring" || echo "not a substring"                                    
it's a substring

この特定のアプローチは、のif-elseステートメントで役立ちますbash。また、主にポータブル

AWK

$ awk '$0~/ab/{print "it is a substring"}' <<< "abcd"                                                             
it is a substring

Python

$ python -c 'import sys;sys.stdout.write("it is a substring") if "ab" in sys.stdin.read() else exit(1)' <<< "abcd"
it is a substring

ルビー

$ ruby -e ' puts "is substring" if  ARGV[1].include? ARGV[0]'  "ab" "abcdef"                                             
is substring

+1は、他のすべての人を超えて進むために。ここで、また他のスタック交換サイトでは、文字列内の部分文字列のオフセットが返されないことに気付きました。これは今夜の使命です:)
WinEunuuchs2Unix

@ WinEunuuchs2Unix bashでそれをするつもりですか?
セルギーKolodyazhnyy

はい、いいえ。私はpythonがすべてのgmail.comメッセージメタデータを取得し、bashがそれを解析し、ドリルダウン付きのGUIリストを提示するFrankensteinプロジェクトを行っています。私はここでも答えを見つけました:stackoverflow.com/questions/5031764/…–
WinEunuuchs2Unix

@ WinEunuuchs2Unix OK。面白そう。個人的には、Pythonですべてを解析することを好みます。テキスト処理には、bash単独よりもはるかに多くの機能があります。
セルギーKolodyazhnyy

私はあなたの好みを約2年間知っており、それらを尊重しています。しかし、私はただPythonを学んでいて、その中でyadを動作させるのは面倒です。bashで私がすでに慣れているすべての配列処理は言うまでもありません。しかし、少なくとも、Googleのgmail.comのすべてをLinuxフラットファイルに吸い込むための最初のpythonスクリプトを作成しましたか?:)
WinEunuuchs2Unix

5

とに注意し[[てください"

[[ $a == z* ]]   # True if $a starts with an "z" (pattern matching).
[[ $a == "z*" ]] # True if $a is equal to z* (literal matching).

[ $a == z* ]     # File globbing and word splitting take place.
[ "$a" == "z*" ] # True if $a is equal to z* (literal matching).

@glenn_jackmanが言ったように、2番目の用語全体を二重引用符で囲むと、テストがリテラルマッチングに切り替わります。

ソース:http : //tldp.org/LDP/abs/html/comparison-ops.html


4

edwinの答えに似ていますが、posixとkshの移植性が向上しており、Richardの場合よりもノイズが少なくなっています。

substring=ab

string=abc
if [ "$string" != "${string%$substring*}" ]; then
    echo "$substring IS in $string"
else
    echo "$substring is NOT in $string"
fi

string=bcd
if [ "$string" != "${string%$substring*}" ]; then
    echo "$string contains $substring"
else
    echo "$string does NOT contain $substring"
fi

出力:

abc contains ab
bcd does NOT contain ab
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.