【问题标题】:script for sum of numbers in file which are written without space with text and special characters文件中数字总和的脚本,这些数字用文本和特殊字符不带空格写入
【发布时间】:2021-06-21 03:05:08
【问题描述】:

假设一个文件有

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=$1
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"

但是他们都没有使用没有空格的数字。

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

【问题讨论】:

  • 所以你希望输出为 11?喜欢1+2+3+1+4
  • 对不起,我用错了句子。它应该是 1 +1 + 4 =6。不应计算括号外的数字
  • 如果你有一个likedef[5:7] 怎么办——这对总和有何贡献?

标签: python bash perl


【解决方案1】:

这如描述的那样工作:

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

打印6

为了理解它,在适当的地方插入一些says:

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

【讨论】:

  • 这给出了一个语法错误 File "tt.py", line 8 if m:=re.findall(r'[([^]]*)]', line): ^ SyntaxError: invalid语法就您的第一个示例而言,文本 abc 只是一个示例。它可以是任何随机文本。
  • if m:=re.findall(r'[([^]]*)]', line): 需要 Python 3.9。如果您有较早的 Python,请将其分成两个不同的语句:m=re.findall(r'[([^]]*)]', line); if m: ...
  • 我纠正了错误,但它给出了错误的值
  • 它适用于您提供的示例。如果它给出了错误的值,那么您的 fie 与您的示例有所不同。
  • 什么是if i == re.findall(r'[([^]]*)]', line)i 是行数,永远不会等于 re.findall 返回的列表
【解决方案2】:

使用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/.*\(\[.\+\]\).*/\1/g;T;p}' test1.txt | sed -e 's/[^0-9]\+/\+/g' -e 's/^\+//g'; cat test1.txt | wc -l) ))

【讨论】:

  • echo $(($(grep -o '[.\+]' test1.txt | sed -z -e 's/[^0-9]\+/\+/g' ; cat test1.txt | wc -l) )) 非法变量名。
  • 我认为命令是正确的。它在我的 bash 中运行良好。你使用 bash 吗?
  • 它说 -z 无效
猜你喜欢
  • 2020-10-30
  • 1970-01-01
  • 2021-01-19
  • 2014-12-09
  • 1970-01-01
  • 1970-01-01
  • 2018-09-29
  • 2018-05-22
相关资源
最近更新 更多