Hitung kemunculan karakter dalam string menggunakan Bash


123

Saya perlu menghitung jumlah kemunculan karakter dalam string menggunakan Bash.

Pada contoh berikut, ketika char adalah (misalnya) t, itu echos jumlah yang benar dari kejadian tdi var, tetapi ketika karakter adalah koma atau titik koma, ia akan mencetak nol:

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

Jawaban:


118

Saya akan menggunakan awkperintah berikut :

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

Saya memisahkan string $char dan mencetak jumlah bidang yang dihasilkan dikurangi 1.

Jika shell Anda tidak mendukung <<<operator, gunakan echo:

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

5
@HattrickNZ Lalu gunakan:$(grep -o "$needle" < filename | wc -l)
hek2mgl

13
@Amir Apa yang Anda harapkan?
hek2mgl

3
Anda dapat melewati wc -l, cukup gunakan grep -c, ini berfungsi pada bsd grep dan linux grep.
andsens

8
@andsens grep -chanya akan menampilkan jumlah baris yang cocok. Itu tidak menghitung beberapa kecocokan per baris.
hek2mgl

1
Saya ingin menghitung '$' dalam sebuah string, bagaimana cara saya melepaskan '$' dari string utama?
masT

117

Anda dapat misalnya menghapus semua karakter lain dan menghitung yang tersisa, seperti:

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

akan mencetak

,,,
3

atau

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

atau

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

atau

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

atau

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

atau

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

1
beberapa trik lagi di sini sepertiy="${x//[^s|S]}"; echo "${#y}"
Aquarius Power

4
gunakan yang pertama, harus selalu menghindari menggunakan proses pemijahan lain untuk melakukan pekerjaan seperti ini, ini dapat sangat mempengaruhi kinerja saat menggunakan dengan loop iterasi besar. Sebagai aturan, eksekusi proses eksternal harus menjadi pilihan terakhir saat menggunakan operasi berulang atau berulang.
osirisgothra

Kenapa kamu tidak suka wc? Ini golf!
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

1
@CiroSantilli 六四 事件 法轮功 包 卓 轩 karena misalnyaecho -n some line | wc -l
jm666

Kode blok 4 adalah yang terbaik menurut saya. Kita perlu membuatnya lebih mudah untuk sampai ke:tr -dc ',' <<<"$var" | wc -c
bgStack15

68

Anda dapat melakukannya dengan menggabungkan trdanwc perintah. Misalnya, menghitung edalam string referee

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

keluaran

4

Penjelasan: Perintah tr -cd 'e' menghapus semua karakter selain 'e', ​​dan Command wc -cmenghitung karakter yang tersisa.

Beberapa baris masukan juga bagus untuk solusi ini, seperti perintah cat mytext.txt | tr -cd 'e' | wc -cdapat dihitung edalam file mytext.txt, meskipun file tersebut mungkin berisi banyak baris.


3
Solusi Anda tampaknya yang paling bersih dan paling mudah diingat, terima kasih!
jirislav

Ini bagus. Terima kasih!
Kodie Grantham

Saya suka ini, karena saya benci awk!
franzisk

3

Membangun jawaban dan komentar hebat dari semua orang, ini adalah versi terpendek dan termanis:

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


2

awk bekerja dengan baik jika server Anda memilikinya

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

Hanya sebagai catatan: awk -F,mencari file ,. Anda dapat melakukan hal berikut:awk -F"${your_char}"
Emixam23

1

Saya akan menyarankan yang berikut:

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

Tidak ada panggilan ke program lain


1

lihat juga ini, misalnya kami ingin menghitung t

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

atau dalam python

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

atau bahkan lebih baik, kita dapat membuat script kita menjadi dinamis dengan awk

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

dalam hal ini keluarannya seperti ini:

e 1
s 1
t 2
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.