この問題はシェルスクリプトで解決する必要があります。以下の文字列の発生回数を数えていますが、abc
私が望む答えは3です。
echo abcsdabcsdabc | grep -o abc
abc
abc
abc
-o
オプションがないと仮定すると、どのように処理するgrep
必要がありますか?
答え1
文字列は次の区切りフィールドで構成されていると思いますabc
。
$ echo abcsdabcsdabc | awk -F 'abc' '{ print (length > 0 ? NF - 1 : 0) }'
3
区切り文字の発生回数は、abc
1 から区切り文字が区切られたフィールドの数を引いたものです。
$ echo abcsdabcsdabc | awk '{ n=0; while (sub("abc", "xxx")) n++; print n }'
3
abc
その後、その行の部分文字列が置き換えられ、xxx
完了した回数が計算され、その数が出力されます。n=0
入力行が1行だけの場合は必要ありません。
gsub()
の関数はawk
置換回数を返すので、上記の内容は次のように単純化できます。
$ echo abcsdabcsdabc | awk '{ print gsub("abc", "xxx") }'
3
では、bash
このプログラムで行ったのと同じことができます。awk
sub()
string=abcsdabcsdabc
n=0
while [[ $string == *abc* ]]; do
n=$(( n+1 ))
string=${string/abc/xxx} # replace first occurrence of "abc" with "xxx"
done
printf '%d\n' "$n"
while
これは、上記の2番目のプログラムと同様に、inが見つからなくなるまでループを使用してin値の部分文字列を置き換えます。abc
$string
xxx
abc
$string
awk
答え2
そしてawk
:
awk -- 'BEGIN{print gsub(ARGV[2], "&", ARGV[1])}' abcsdabcsdabc abc
パターン(ここでは)は拡張正規表現(/supported正規表現に似ています)abc
として扱われます。awk
grep -E
egrep
この構文を使用すると、トピックと正規表現に複数の行を含めることができます。私たちも避けるecho
ランダムデータをエクスポートできない場合のよくある質問。
perl
正規表現を使用してください(GNUに似ていますgrep -P
):
perl -le 'print scalar (() = $ARGV[0] =~ m{$ARGV[1]}g)' -- abcsdabcsdabc abc
é
(ただし、ロケールのエンコードによっては、引数はテキストとして解釈されません。たとえば、UTF-8ロケールで .
引数を使用すると、1(文字)ではなく2(バイト)が報告されます。
を使用すると、zsh
次のことができます。
occurrences() {
set -o localoptions -o extendedglob
local n=0
: ${1//(#m)$2/$((++n))}
echo $n
}
occurrences abcsdabcsdabc abc
ここで、2番目の引数(abc
)は固定文字列として解釈されます。代わりに、$2
拡張され$~2
たzsh globパターン(拡張正規表現よりも広範な機能セットを持っていますが、構文は異なります)として解釈されます。
答え3
Raku(以前のPerl_6)の使用
~$ echo "abcsdabcsdabc" | raku -ne '.match("abc", :global).say;'
(「abc」 「abc」 「abc」)
一致は上に示されています(1行ずつ)。一致する項目の数(1行)は次のとおりです。
~$ echo "abcsdabcsdabc" | raku -ne '.match("abc", :global).elems.say;'
3
注::global
パラメータはに省略できます:g
。
HTH。
答え4
GNUの使用sed
echo abcsdabcsdabc | sed 's/abc/abc\n/g' | wc -w