简体   繁体   English

如何在不使用wc的情况下使用perl在STDIN中计算字符?

[英]How can I count the characters in STDIN using perl without wc?

I am attempting to write a script to count the number of lines, words, and characters input by the user in STDIN. 我试图编写一个脚本来计算用户在STDIN中输入的行数,单词数和字符数。 Using the script below, I can accomplish this when a user inputs a file as a CLI, but when I attempt to use this code for STDIN, I end up with an infinite loop. 使用下面的脚本,当用户输入文件作为CLI时,我可以完成此操作,但是当我尝试将此代码用于STDIN时,最终会出现无限循环。 What should I change to fix this? 我应该改变些什么来解决这个问题?

print "Enter a string to be counted";
my $userInput = <STDIN>;
while ($userInput) {
        $lines++;
        $chars += length ($_);
        $words += scalar(split(/\s+/, $_));
}
printf ("%5d %5d %5d %10s", $lines, $words, $chars, $fileName);

Your program is fine, expect that you need to read from the file handle in the while test. 您的程序很好,希望您需要在while测试中从文件句柄读取 At present you are just reading one line from STDIN and repeatedly checking that it is true - ie not zero or undef . 目前,您只是从STDIN中读取一行,并反复检查它是否为 -即不是零或undef

Your code should look like this 您的代码应如下所示

use strict;
use warnings;

my ($lines, $chars, $words) = (0, 0, 0);

print "Enter a string to be counted";

while (<STDIN>) {
  ++$lines;
  $chars += length;
  $words += scalar split;
}

printf "%5d %5d %5d\n", $lines, $words, $chars;

Note that I have used just length instead of length $_ as $_ is the default parameter for the length operator. 请注意,我只使用了length而不是length $_因为$_length运算符的默认参数。 $_ only really comes into its own if you use the defaults. $_仅在使用默认值时才真正发挥作用。

Similarly, the default parameters to split are split ' ', $_ which is what you want in preference to split /\\s+/, $_ because the latter returns a zero-length initial field if there are any leading spaces in $_ . 同样,要split的默认参数是split ' ', $_ ,这是您想要优先split /\\s+/, $_原因split /\\s+/, $_因为如果$_有任何前导空格,后者会返回零长度的初始字段。 The special value of a single literal space ' ' just extracts all the sequences of non-space characters, which is almost always what you want. 单个文字空间' '的特殊值只会提取所有非空格字符序列,这几乎总是您想要的。 Anything other than just a single space is converted to a regex pattern as normal. 除单个空格外,其他所有内容都将正常转换为regex模式。

Finally, I have used ++$lines instead of $lines++ . 最后,我用++$lines代替$lines++ The latter is popular only because of the name of the language C++, and it is less common that the value returned by the expression needs to be the original value of the variable rather than the new one. 后者之所以流行是因为C ++语言的名字,而表达式返回的值需要是变量的原始值,而不是值,这种情况很少见。 Much more often the increment is used as a statement on its own, as here, when the returned value is irrelevant. 当返回的值无关紧要时,增量通常会单独用作语句,如此处所示。 If Perl didn't optimise it out (because the context is void and the return value is unused) the code would be doing unnecessary additional work to save the original value of the variable so that it can be returned after the increment. 如果Perl没有对其进行优化(因为上下文为空,并且未使用返回值),则代码将做不必要的额外工作来保存变量的原始值,以便可以在增量后返回它。 I also think ++$var looks more like the imperative "increment $var " and improves the readability of the code. 我还认为++$var看起来更像是命令性的“递增$var ”,并提高了代码的可读性。

Your input has to be within the loop. 您的输入必须在循环内。 Else you are processing the same string over and over again. 否则,您将一遍又一遍地处理相同的字符串。

Maybe this is what you need? 也许这就是您所需要的?

use strict;
use warnings;

print "Enter a string to be counted:\n";
my $lines = 0;
my $chars = 0;
my $words = 0;
while (<>) {
    chomp;
    $lines++;
    $chars += length ($_);
    $words += scalar(split(/\s+/, $_));
}
printf ("lines: %5d words: %5d chars: %5d\n", $lines, $words, $chars);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM