文件中数字总和的脚本,这些数字在没有 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) ))
- 用括号提取行。
- 用+替换非数字。
- 获取文件中的行数。
- 作为算术表达式计算。
如果括号在一行中多次出现,请使用 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) ))
假设一个文件有
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) ))
- 用括号提取行。
- 用+替换非数字。
- 获取文件中的行数。
- 作为算术表达式计算。
如果括号在一行中多次出现,请使用 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) ))