有没有更好的方法来计算字符串中 char 的出现次数?

Is there a better way to count occurrence of char in a string?

我觉得必须有更好的方法来计算出现次数,而不是用 perl 编写子程序,shell 在 Linux。

#/usr/bin/perl -w
use strict;
return 1 unless [=10=] eq __FILE__;
main() if [=10=] eq __FILE__;
sub main{
    my $str = "ru8xysyyyyyyysss6s5s";
    my $char = "y";
    my $count = count_occurrence($str, $char);
    print "count<$count> of <$char> in <$str>\n";
}
sub count_occurrence{
    my ($str, $char) = @_;
    my $len = length($str);
    $str =~ s/$char//g;
    my $len_new = length($str);
    my $count = $len - $len_new;
    return $count;
}

计算字符串中字符出现的次数可以用 Perl 中的一行来执行(与 4 行相比)。不需要 sub(尽管将功能封装在 sub 中没有错)。来自 perlfaq4 "How can I count the number of occurrences of a substring within a string?"

use warnings;
use strict;

my $str = "ru8xysyyyyyyysss6s5s";
my $char = "y";
my $count = () = $str =~ /\Q$char/g;
print "count<$count> of <$char> in <$str>\n";

漂亮*Bash/Coreutils/Grep单行:

$ str=ru8xysyyyyyyysss6s5s
$ char=y
$ fold -w 1 <<< "$str" | grep -c "$char"
8

或者也许

$ grep -o "$char" <<< "$str" | wc -l
8

第一个只有当子字符串只有一个字符长时才有效;第二个仅在子字符串不重叠时才有效。

* 不是真的。

toolic 给出了正确答案,但您可能会考虑不对您的值进行硬编码以使程序可重用。

use strict;
use warnings;

die "Usage: [=10=] <text> <characters>" if @ARGV < 1;
my $search = shift;                    # the string you are looking for
my $str;                               # the input string
if (@ARGV && -e $ARGV[0] || !@ARGV) {  # if str is file, or there is no str
    local $/;                          # slurp input
    $str = <>;                         # use diamond operator
} else {                               # else just use the string
    $str = shift;
}
my $count = () = $str =~ /\Q$search\E/gms;
print "Found $count of '$search' in '$str'\n";

这将允许您使用该程序来计算字符或字符串在字符串、文件或标准输入中的出现次数。例如:

count.pl needles haystack.txt
some_process | count.pl foo
count.pl x xyzzy

如果字符是常量,下面的最好:

my $count = $str =~ tr/y//;

如果字符是可变的,我会使用以下内容:

my $count = length( $str =~ s/[^\Q$char\E]//rg );

如果我想与早于 5.14 的 Perl 版本兼容(因为它速度较慢且使用更多内存),我只会使用以下内容:

my $count = () = $str =~ /\Q$char/g;

以下不使用内存,但可能有点慢:

my $count = 0;
++$count while $str =~ /\Q$char/g;