Đếm số lần xuất hiện của một ký tự trong một chuỗi bằng cách sử dụng Bash


123

Tôi cần đếm số lần xuất hiện của một ký tự trong một chuỗi bằng cách sử dụng Bash.

Trong ví dụ sau, khi ký tự là (ví dụ) t, nó echo số lần xuất hiện chính xác của tin var, nhưng khi ký tự là dấu phẩy hoặc dấu chấm phẩy, nó sẽ in ra số 0:

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

Câu trả lời:


118

Tôi sẽ sử dụng awklệnh sau :

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

Tôi đang tách chuỗi theo $charvà in số trường kết quả trừ đi 1.

Nếu trình bao của bạn không hỗ trợ <<<toán tử, hãy sử dụng echo:

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

5
@HattrickNZ Sau đó, sử dụng:$(grep -o "$needle" < filename | wc -l)
hek2mgl

13
@Amir Bạn mong đợi điều gì?
hek2mgl

3
Bạn có thể bỏ qua wc -l, chỉ cần sử dụng grep -c, nó hoạt động trên cả grep bsd và grep linux.
andsens

8
@andsens grep -csẽ chỉ xuất ra số dòng phù hợp. Nó không tính nhiều kết quả phù hợp trên mỗi dòng.
hek2mgl

1
Tôi muốn đếm '$' trong một chuỗi, làm cách nào để thoát '$' khỏi chuỗi chính?
masT

117

Ví dụ, bạn có thể xóa tất cả các ký tự khác và đếm những gì còn lại, như:

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

sẽ in

,,,
3

hoặc là

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

hoặc là

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

hoặc là

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

hoặc là

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

hoặc là

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

1
một số trick hơn ở đây nhưy="${x//[^s|S]}"; echo "${#y}"
Bảo Bình điện

4
sử dụng cái đầu tiên, nên luôn tránh dùng đến việc tạo ra một quy trình khác để thực hiện công việc như thế này, nó có thể ảnh hưởng nghiêm trọng đến hiệu suất khi sử dụng với các vòng lặp lớn. Theo quy tắc, thực thi quy trình bên ngoài nên là phương sách cuối cùng khi sử dụng các hoạt động lặp lại hoặc lặp lại.
osirisgothra

Tại sao bạn không thích wc? Nó chơi gôn!
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

1
@CiroSantilli 六四 事件 法轮功 包 卓 轩 vì ví dụecho -n some line | wc -l
jm666

Mã khối 4 là tốt nhất theo ý kiến ​​của tôi. Chúng tôi cần làm cho nó dễ dàng hơn để truy cập:tr -dc ',' <<<"$var" | wc -c
bgStack15

68

Bạn có thể làm điều đó bằng cách kết hợp trwclệnh. Ví dụ: đếm etrong chuỗi referee

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

đầu ra

4

Giải thích: Lệnh tr -cd 'e'xóa tất cả các ký tự không phải 'e' và Lệnh wc -cđếm các ký tự còn lại.

Nhiều dòng đầu vào cũng tốt cho giải pháp này, chẳng hạn như lệnh cat mytext.txt | tr -cd 'e' | wc -ccó thể đếm etrong tệp mytext.txt, thậm chí được cho rằng tệp có thể chứa nhiều dòng.


3
Giải pháp của bạn có vẻ là rõ ràng và dễ nhớ nhất, cảm ơn!
jirislav

Điều đó thật tuyệt. Cảm ơn bạn!
Kodie Grantham

Tôi thích điều này, bởi vì tôi ghét awk!
franzisk

3

Dựa trên những câu trả lời và nhận xét tuyệt vời của mọi người, đây là phiên bản ngắn nhất và ngọt ngào nhất:

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


2

awk hoạt động tốt nếu bạn máy chủ của bạn có nó

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

Cũng như một lưu ý: awk -F,tìm kiếm a ,. Bạn có thể làm như sau:awk -F"${your_char}"
Emixam23

1

Tôi sẽ đề xuất những điều sau:

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

Không có cuộc gọi đến bất kỳ chương trình nào khác


1

cũng kiểm tra điều này, chẳng hạn như chúng tôi muốn đếm t

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

hoặc trong python

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

hoặc thậm chí tốt hơn, chúng tôi có thể làm cho tập lệnh của mình động với awk

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

trong trường hợp này đầu ra là như thế này:

e 1
s 1
t 2
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.