我有一个巨大的文本文件,其中约有 70k 行。我的目标是读取此文件,匹配模式(“计数”),并用迭代数字添加或替换其值。
我正在做的是:
- 读取文件。
- Grep 查找模式计数。
- 如果匹配,则删除该模式。
- 在该行中追加所需的模式 (Count = $i)。
- 增量变量 i。
这是代码
line_count=0
i=0
while read line
do
line_count=$((line_count+1))
if echo "$line" | grep -q "Count"
then
sed -i "$line_count d" /tmp/$rand_file1
sed -i "$line_count i Count = $i" /tmp/rand_file1
i=$((i+1))
fi
done </tmp/rand_file1
上述技术大约需要25分钟才能完成。有没有办法减少这个时间,因为我将处理更大的数据文件?
以下是输入模式和文件以及预期输出:
输入文件
Count
Name = Sarah
ID = 113
PhNo =
Count
Name = John
ID = 787
PhNo =
Count = 123
Name = Mike
ID = 445
PhNo =
Count Now
Name = Max
ID = 673
PhNo =
预期输出文件
Count = 1
Name = Sarah
ID = 113
PhNo =
Count = 2
Name = John
ID = 787
PhNo =
Count = 3
Name = Mike
ID = 445
PhNo =
Count = 4
Name = Max
ID = 673
PhNo =
答案1
在 shell 中解析文本文件是非常缓慢且极易出错。您grep
在输入文件中的每行运行一次,并sed
为包含Count
.避免这样做。
据我所知,这可能会被替换
awk '$1 == "Count" { printf("Count = %d\n", ++i); next } { print }' rand_file1 >rand_file1.new
Count =
当它命中第一个字段恰好是 的行时,它会输出具有正确增量的行Count
,并按原样传递所有其他行。
或者,
awk '$1 == "Count" { $0 = sprintf("Count = %d", ++i) } { print }' rand_file1 >rand_file1.new
它修改$0
值(输入行)并使用单个print
.
最后一个变体可以缩短为
awk '$1 == "Count" { $0 = sprintf("Count = %d", ++i) } 1' rand_file1 >rand_file1.new
也可以看看 ”为什么使用 shell 循环处理文本被认为是不好的做法?”。
答案2
强制性perl
答案:
perl -pe 's{^Count\b.*}{"Count = " . ++$i}e'
答案3
短的awk
方法:
awk '$1 == "Count"{ $0 = "Count = "++i }1' file
输出:
Count = 1
Name = Sarah
ID = 113
PhNo =
Count = 2
Name = John
ID = 787
PhNo =
答案4
使用sed
, 并通过seq
管道输入进行迭代:
t='Count'
seq -f "$t = %g" 70000 | sed -i -e "/^$t/R /dev/stdin" -e "/^$t/d" /tmp/rand_file1
笔记:
sed
的R
电子头命令在大括号中不起作用{}
,因此-e
需要两个 s。- 可以
70000
是任何足够大的数字。当sed
停止时, 也会停止seq
,因此甚至不会创建更高的值。