我有一个包含如下文本块的 txt 文件:
17-01-2023
Purchase AAA
Apple Pay John Doe
Full Payment
-11,34€
0,11€
30-01-2023
Purchase BBB
Mastercard Jane Doe
Installment
-23,90€
0,24€
因此,我们依次有日期、购买类型、付款类型和姓名、付款类型、负值和折扣。
这些通过包含数千个条目的文件重复。
我想对这些值求和,在此示例中为 11,34 + 23,90,并将总和设为正数。请记住,数字后有一个欧元符号,在我的语言环境中,逗号是小数点分隔符。
我如何从终端使用 sed、awk 等来做到这一点?
您可以使用 awk - 与非数字货币符号前缀(如 )不同
€-23,90
,在数字转换期间将忽略非数字后缀。请注意,不同的实现可能会以不同方式处理语言环境的小数点分隔符,例如。respects
LC_NUMERIC
/LC_ALL
as required for POSIX compliance,而 GNU awk 默认偏离 POSIX 规范,需要被指示使用您的语言环境:请参阅位于Locales Can Influence Conversion的 GNU Awk 用户指南
例如,使用 de_DE.UTF-8 语言环境进行测试:
在 Mac 操作系统上:
假设交易金额始终在记录的第 5 行,记录开始由“DD-MM-YYYY”格式的日期表示,并且这种模式只能出现在记录开始处,以下
awk
程序会做:它的工作原理如下:
locale decimal_point
作为变量传递dpt
给程序。这是相关的,因为您似乎awk
在输入,
格式化为小数点分隔符的设置中使用,但区域设置设置为使用.
,导致awk
错过数字的小数部分。line_of_record
为 0。line_of_record
计数器。如果它达到 5,它将用,
a替换.
(如有必要),以便awk
将行内容解释为十进制数,并从变量中减去行内容以求total
和正支付值。这是比最低限度需要更多的代码,但如果应该有空行分隔记录(它仍然依赖于记录的第 5 行中的交易金额),程序会更健壮一些。
这只是为了好玩 - 假设 GNU sed 用于
n~m
构造:,
(当然,如果需要,您可以添加另一个 sed 或 tr 将小数点转换回原始语言环境)。使用Raku(以前称为 Perl_6)
没有类型检查:
通过类型检查:
-ne
简而言之,Raku 在带有非自动打印标志的命令行中运行。标量变量$sum1
是state
d,这意味着它将在由标志引导的循环-ne
开始之前实例化。在第二条语句中,如果一个匿名递增行计数器变量++$
在%
模数除以 6 时等于 5,则将逗号trans
延迟到点并删除(不带任何内容)欧元符号。然后累加到变量中。在循环的最后,。,
.
subst
€
+=
$sum
END
say $sum1
示例输入:
示例输出:
对于累计总数,只有
say
累计变量:示例输出:
受@AdminBee's
awk
answer 的启发,如果仅当行包含字符时才增加行计数器,则可以容忍记录之间的空行.chars
:样本输出(同上):
请注意,OP 示例中给出的数字
Rat
在 Raku 中默认输入为离子数字(Raku 中可用的其他类型包括Num
s 和Int
s)。Rat
Raku 中的 s(假设它们足够小)通常不会出现舍入错误,并且会很快转换为分数。例如,将END
语句更改为:示例输出:
为了更快的操作,
say $sum1.nude
返回(-881 25)
.https://docs.raku.org/language/numerics.html#Rational
https://raku.org