文件中数字总和的脚本,这些数字在没有 space 的情况下编写,带有文本和特殊字符

script for sum of numbers in file which are written without space with text and special characters

假设一个文件有

abc[1:0]
2 abc
abc 3
[1:0] abc

我有一个很大的文件。现在,如果我想对所有数字求和,如下所示。

注意括号外的数字不计算。

1+1+numberoflines

在这种情况下 1+1+4 =6

我该怎么做?

我尝试了很多方法,比如

perl -nle '$sum+=$_} END { print $sum' test1.txt

n=
sum=0
sd=0
while [ $n -gt 0 ]
do
    sd=`expr $n % 10`
    sum=`expr $sum + $sd`
    n=`expr $n / 10`
done
echo  "Sum of digit for numner is $sum"

但是其中 none 个数字没有空格。

请注意,abc 只是一个示例。它可以是任何带有数字的随机文本

这按描述工作:

echo 'abc[1:0]
2 abc
abc 3
[1:0] abc' | perl -lnE 'while (/\[([^]]*)\]/g) { 
                            $s=;
                            while ($s=~/\b(\d+)\b/g) {
                                $sum+=;
                            }
                        }   
                        END {
                        say $sum+$.
                        }
'

打印 6

为了理解,在适当的地方插入一些say

echo 'abc[1:0]
2 abc
abc 3
[1:0] abc' | perl -lnE 'while (/\[([^]]*)\]/g) { 
                            $s=;
                            say $s;
                            while ($s=~/\b(\d+)\b/g) {
                                say ;
                                $sum+=;
                            }
                        }   
                        END {
                        say $.;
                        say $sum+$.
                        }
'
1:0      first bracketed group from /\[([^]]*)\]/g
1        digits within from $s=~/\b(\d+)\b/g
0
1:0
1
0
4        line count from $.
6        $sum + line count

对于 Python 解决方案,您可以使用相同的正则表达式并执行:

import re 

total=0
with open(fn) as f:        # 'fn' is the path to your file
    for i, line in enumerate(f, 1):
        if m:=re.findall(r'\[([^]]*)\]', line): 
            for e in m:
                total+=sum(map(int, re.findall(r'\b(\d+)\b', e)))
                
print(total+i)      

此正则表达式存在局限性:它不会处理不平衡或嵌套的括号。那是一个更复杂的正则表达式。

Python 注:

if m:=re.findall(r'\[([^]]*)\]', line): 中的 := 仅为 Python 3.9。 将早期 Python 版本分成两个语句:

m=re.findall(r'\[([^]]*)\]', line)
if m:
    ...

使用grep和sed,如下:

echo $(( $(grep -o '\[.\+\]' test1.txt | sed -e 's/[^0-9]\+/\+/g' -e 's/^\+//g' ; cat test1.txt | wc -l) ))
  1. 用括号提取行。
  2. 用+替换非数字。
  3. 获取文件中的行数。
  4. 作为算术表达式计算。

如果括号在一行中多次出现,请使用 sed 而不是 grep。

echo $(( $(sed -n -e '{s/.*\(\[.\+\]\).*//g;T;p}' test1.txt | sed -e 's/[^0-9]\+/\+/g' -e 's/^\+//g'; cat test1.txt | wc -l) ))