如何对 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 到 wc
和 cut
只是为了计算文件中的行数有点笨拙。
您的要求不是很清楚,但此 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 语法中进行的。
您指出 tcsh
但 expr
是 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
我正在尝试计算一组日志文件中的条目数。其中一些日志包含不应计数的行(这些日志的数量保持不变)。我想要解决这个问题的方法是一个迭代散列的 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 到 wc
和 cut
只是为了计算文件中的行数有点笨拙。
您的要求不是很清楚,但此 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 语法中进行的。
您指出 tcsh
但 expr
是 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