如何对 shell 命令的输出执行算术运算

How to perform arithmetic operations on the output of a shell command

我正在尝试计算一组日志文件中的条目数。其中一些日志包含不应计数的行(这些日志的数量保持不变)。我想要解决这个问题的方法是一个迭代散列的 Perl 脚本,它将日志名称映射到一个单行,获取该特定日志的条目数(我认为这比几十个更容易维护if-else 语句)

获取行数很简单:

wc -l [logfile] | cut -f1 -d " "

问题是当我需要从该值中减去 1 或 2 时。我尝试了以下方法:

expr( wc -l [logfile] | cut -f1 -d " " ) - 1

但这会导致错误:

Badly placed ()'s.

: Command not found.

如何对 shell 命令的输出执行算术运算?有更好的方法吗?

显示比 bash 或任何类似 shell 的行数少一:

echo $(( $(wc -l <file) - 1 ))

讨论

要获取行数,您使用了:

wc -l logfile | cut -f1 -d " " 

cut 在这里是必需的,因为 wc 将文件名复制到它的输出中。为避免这种情况,从而避免需要 cut,通过标准输入将输入提供给 wc

wc -l <logfile

现代(POSIX)shells,算术是用$((...))完成的。因此,我们可以通过以下方式从行数中减去:

$(( $(wc -l <file) - 1 ))

从 shell 到 wccut 只是为了计算文件中的行数有点笨拙。

您的要求不是很清楚,但此 Perl 代码创建了一个散列,将当前目录中的每个日志文件与其包含的行数相关联。它的工作原理是将每个文件读入一个行数组,然后在标量上下文中评估该数组以给出行数。我希望如何从每行计数中减去常数增量是显而易见的。

use strict;
use warnings;

my %lines;

for my $logfile ( glob '*.log' ) {

    my $num_lines = do {
        open my $fh, '<', $logfile or die qq{Unable to open "$logfile" for input: $!};
        my @lines = <$fh>;
    };

    $lines{$logfile} = $num_lines;
}

更新

经过w.k的评论,我觉得这个版本可能会更好

use strict;
use warnings;

my %lines;

for my $logfile ( glob '*.log' ) {
    open my $fh, '<', $logfile or die qq{Unable to open "$logfile" for input: $!};
    1 while <$fh>;
    $lines{$logfile} = $.;
}

现有答案的方向是解决您在 perl 中的问题,但您自己的实验是在 shell 语法中进行的。

您指出 tcshexpr 是 Posix shell 语法。

这里是一个 csh 脚本的例子,它计算一个文件中的行数,它的名称被传递,然后对行数进行算术运算。

set lines=`wc -l < `
@ oneless = ($lines - 1)
echo "There are $lines in  and minus one makes $oneless"

测试:

csh count.csh count.csh
There are 3 lines in count.csh and minus one makes 2