Bash kullanarak bir dizedeki bir karakterin oluşumlarını sayma


124

Ben saymak gerekir bir dizgede bir karakterin yineleme sayısını Bash kullanarak.

Aşağıdaki örnekte, kömür olduğu zaman, (örneğin) t, bu echos yinelenme sayısını doğru tolarak varfakat karakter virgül veya noktalı olduğunda, sıfır basar

var = "text,text,text,text" 
num = `expr match $var [,]`
echo "$num"

Yanıtlar:


118

Şu awkkomutu kullanırdım:

string="text,text,text,text"
char=","
awk -F"${char}" '{print NF-1}' <<< "${string}"

Dizeyi bölüyorum ve $charelde edilen alanların sayısı eksi 1'i yazdırıyorum.

Kabuğunuz <<<operatörü desteklemiyorsa , şunu kullanın echo:

echo "${string}" | awk -F"${char}" '{print NF-1}'

5
@HattrickNZ O zaman şunu kullanın:$(grep -o "$needle" < filename | wc -l)
hek2mgl

13
@Amir Ne bekliyorsunuz?
hek2mgl

3
Atlayabilirsiniz wc -l, sadece kullanın grep -c, hem bsd grep hem de linux grep üzerinde çalışır.
andsens

8
@andsens grep -cyalnızca eşleşen satır sayısını verir. Satır başına birden fazla eşleşme sayılmaz.
hek2mgl

1
Bir dizedeki '$' ları saymak istiyorum, ana dizeden '$' dan nasıl kaçabilirim?
masT

118

örneğin diğer tüm karakterleri kaldırabilir ve kalanları sayabilirsiniz, örneğin:

var="text,text,text,text"
res="${var//[^,]}"
echo "$res"
echo "${#res}"

yazdıracak

,,,
3

veya

tr -dc ',' <<<"$var" | awk '{ print length; }'

veya

tr -dc ',' <<<"$var" | wc -c    #works, but i don't like wc.. ;)

veya

awk -F, '{print NF-1}' <<<"$var"

veya

grep -o ',' <<<"$var" | grep -c .

veya

perl -nle 'print s/,//g' <<<"$var"

1
Burada biraz daha hüner gibiy="${x//[^s|S]}"; echo "${#y}"
Kova Güç

4
Birincisini kullanın, her zaman böyle bir iş yapmak için başka bir işlem üretmekten kaçınmalısınız, büyük yineleme döngüleri ile kullanıldığında performansı ciddi şekilde etkileyebilir. Kural olarak, tekrarlayan veya yinelenen işlemler kullanılırken harici işlem yürütme son çare olmalıdır.
osirisgothra

Neden böyle değil mi wc? Golf oynuyor!
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

1
@CiroSantilli 六四 事件 法轮功 包 卓 轩 çünkü örneğinecho -n some line | wc -l
jm666

Kod bloğu 4 bence en iyisi. tr -dc ',' <<<"$var" | wc -c
Aşağıdakilere ulaşmayı

69

Bunu trve wckomutlarını birleştirerek yapabilirsiniz . Örneğin e, dizede saymak için referee

echo "referee" | tr -cd 'e' | wc -c

çıktı

4

Açıklamalar: Komut tr -cd 'e', 'e' dışındaki tüm karakterleri kaldırır ve Komut wc -ckalan karakterleri sayar.

Dosyanın birçok satır içerebileceği düşünülse bile, komutun dosyadaki cat mytext.txt | tr -cd 'e' | wc -csayımları gibi birden çok girdi satırı da bu çözüm için iyidir .emytext.txt


3
Çözümünüz en temiz ve hatırlaması en kolay gibi görünüyor, teşekkürler!
jirislav

Bu harika. Teşekkür ederim!
Kodie Grantham

Bunu seviyorum, çünkü kötülükten nefret ediyorum!
franzisk

3

Herkesin harika cevaplarına ve yorumlarına dayanan bu en kısa ve en tatlı versiyon:

grep -o "$needle" <<< "$haystack" | wc -l


2

awk, sunucunuzda varsa iyi çalışıyor

var="text,text,text,text" 
num=$(echo "${var}" | awk -F, '{print NF-1}')
echo "${num}"

Bir not olarak: awk -F,bir ,. Aşağıdakileri yapabilirsiniz:awk -F"${your_char}"
Emixam23

1

Aşağıdakileri öneririm:

var="any given string"
N=${#var}
G=${var//g/}
G=${#G}
(( G = N - G ))
echo "$G"

Başka bir programa çağrı yok


1

Şuna da bir bakın, örneğin saymak istiyoruz t

echo "test" | awk -v RS='t' 'END{print NR-1}'

veya içinde python

python -c 'print "this is for test".count("t")'

hatta daha iyisi, senaryomuzu dinamik hale getirebiliriz awk

echo 'test' | awk '{for (i=1 ; i<=NF ; i++) array[$i]++ } END{ for (char in array) print char,array[char]}' FS=""

bu durumda çıktı şu şekildedir:

e 1
s 1
t 2
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.