文字列の一部を認識しながら文字列を検索し、文字列を返す


9

たとえば、文字列があります

"Icecream123 AirplaneBCD CompanyTL1 ComputerYU1"

私の文字列には必ず部分文字列IceCreamが含まれていることはわかっていますが、その後に何があるかわかりません。

それは私の例のように123かもしれませんし、何か違うかもしれません。

次のコマンドを使用して、grepを使用して文字列に「Icecream」サブストリングが存在するかどうかを検出できますが

echo $string | grep -oF 'Icecream';

どちらが印刷されます

Icecream

部分文字列全体を出力するコマンドを使用したいのですが、私の例では

Icecream123

もちろん、アイスクリームに続くものはランダムで事前にわかっていないので、私はただ行うことができません

$SUBSTRING=$(echo $string | grep -oF 'Icecream')
$SUBSTRINGTRAIL=123
echo $SUBSTRING$SUBSTRINGTRAIL

サブストリングは固定/静的です-常に「アイスクリーム」ですか、それとも可変ですか?
ジェフシャラー

スペースは目的のサフィックスの終わりを示しますか?
ジェフシャラー

@JeffSchaller残念ながら、私にはわかりません。私は実際に別のコマンドから複数行の出力を取得しています。これは変数に格納します。この変数は$ stringです。エコーされると、複数行の出力がそれらの間にスペースのある信号線として表示されます。それがスペースなのか、LFなどの特殊文字なのか、実際にはわかりません。空間だと思いました。
Sonamor

たとえば、Icecream123 AirplaneBCDあなたはに立ち寄りたいのです123。それは、3の後にスペースがあるからでしょうか、それとも他の何かですか?
ジェフシャラー

1
データが何かわからない場合、適切なソリューションを作成するのは困難です。これまでのすべての答えは、あなたが示したように、データが1行にあると想定しています。私はあなたの区切り文字が何であるかを理解しようとしていました-「末尾」の部分はどこで停止すべきか
ジェフシャラー

回答:


15

grepperl互換の正規表現をサポートしている場合、次の単語境界まで貪欲に一致しない可能性があります。

echo "$string" | grep -oP 'Icecream.*?\b'

それ以外の場合は、非ブランク文字の最も長いシーケンスに一致します。

echo "$string" | grep -o 'Icecream[^[:blank:]]*'

または、すべてをシェルに保持し、スペースで始まる最も長い末尾の文字シーケンスを削除します。

echo "${string%% *}"

2
PCREでは、'Icecream\S+'いくつかの非空白文字に使用します。
グレンジャックマン

コメントをありがとう、残念ながら私のバージョンのgrepはperl regexをサポートしていないようです。3つ目のオプションについて、もう少し詳しく説明してもらえますか?それを実装する方法がよくわかりません。
Sonamor

もう少しテストした後、エコー "$ string"を使用しているようです| grep -oP 'Icecream。*?\ b'または 'Icecream \ S +'を実行します。ありがとう
Sonamor

$ string変数は文字列ですが、それでも二重引用符で囲む必要があるのは本当に混乱しています!
Sonamor

この場合の@Sonamor引用は厳密には必要ありません。しかし、それ、それが入り込むのが良い習慣であるという非常に多くの場合があります。たとえば、二重引用符が必要な場合を
スチールドライバー

7

grep知っているを使用する-o

$ printf '%s\n' "$string" | grep -o '\<Icecream[^[:blank:]]*'
Icecream123

パターン\<Icecream[^[:blank:]]*は、文字列IcecreamI単語の前に非単語文字または行の先頭が続く)の後に0個以上の非空白文字(スペースやタブではない)が続く文字列に一致します。


使用awk

$ printf '%s\n' "$string" | awk -v RS=' ' '/^Icecream/'       
Icecream123

awkプログラムは、スペースで区切られたレコードに文字列を分割し、それぞれをテストします。文字列で始まるものを出力しますIcecream

mawkまたはGNU を使用して、以下を使用awkすることもできます

printf '%s\n' "$string" | awk -v RS='[[:blank:]]' '/^Icecream/'

RS複数の文字が含まれている場合、正規表現として解釈されるためです。


sed、同様の方法でgrep

$ printf '%s\n' "$string" | sed 's/.*\(\<Icecream[^[:blank:]]*\).*/\1/'
Icecream123

使用/bin/sh

set -- Icecream123 AirplaneBCD CompanyTL1 ComputerYU1
for string; do
    case $string in
        Icecream*)
            printf '%s\n' "$string"
            break
    esac
done

Perl(から少し助けてtr):

$ printf '%s\n' "$string" | tr ' ' '\n' | perl -ne '/Icecream\S*/ && print'
Icecream123

あるいは単に

$ printf '%s\n' "$string" | perl -ne '/(Icecream\S*)/ && print $1, "\n"'
Icecream123

または、行に分割し、キーと一致:echo "$string" | grep -o '\S\+' | grep "Icecream"
アイザック

7

bashにタグを付けてから:

[[ $string =~ (Icecream[^ ]*) ]] && result=${BASH_REMATCH[1]}

より一般的には、次の検索語について$search

[[ $string =~ ($search[^ ]*) ]] && result=${BASH_REMATCH[1]}

...またはパラメータ展開を使用:

# remove any leading text up to -and through- the search text:
x=${string##*$search}

# remove any trailing space onwards
result=$search${x%% *}


1

特に、あなたのバージョンのgrepがperl regexをサポートしていないと言っているので、おそらくもう少し簡単です:

$ echo $string | tr ' ' '\n' | grep 'Icecream' Icecream123

tr、すべてのスペースを改行で置き換えることにより、文字列を行に分割します。その後、grep簡単に使用できます。

また、次のように記述して、探している単語に続くものだけを取得することもできます。

$ echo $string | tr ' ' '\n' | sed -n 's/Icecream//p' 123

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