用迭代值替换大文件中的计数器字段

用迭代值替换大文件中的计数器字段

我有一个巨大的文本文件,其中约有 70k 行。我的目标是读取此文件,匹配模式(“计数”),并用迭代数字添加或替换其值。

我正在做的是:

  1. 读取文件。
  2. Grep 查找模式计数。
  3. 如果匹配,则删除该模式。
  4. 在该行中追加所需的模式 (Count = $i)。
  5. 增量变量 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

笔记:

  • sedR电子头命令在大括号中不起作用{},因此-e需要两个 s。
  • 可以70000是任何足够大的数字。当sed停止时, 也会停止seq,因此甚至不会创建更高的值。

相关内容