对文本文件中的所有字符进行操作的更快方法

Faster method to operate on all characters in a text file

我想在一个很长的字符串上执行一个任务,我认为我需要对每个字符单独进行操作。在这样做之前,我首先尝试 建立访问所有这些字符所需时间的基线

我打算使用的输入是一个文本文件,其中单行包含一个由数字组成的单词

下面的代码是我迄今为止最好的尝试,是否有更快的方法逐个访问字符串中的所有字符

function handle_split() {
    split=
    while read -N 1 char; do
        :
    done
}

while read -N 100000 split; do
    ((i=i%100)); ((i++==0)) && wait
    handle_split $split &
done < "filename.txt"

此行旨在避免同时排队超过 100 个任务

((i=i%100)); ((i++==0)) && wait

拆分的长度是根据输入的已知长度进行硬编码的,在这种情况下,我使用的是大约十亿个字符的字符串。


顺便说一句,我尝试将我的字符串拆分转换为数组以寻求性能提升。

function handle_split() {
    split=($@)
    for char in ${split[@]}; do
        :
    done
}

while read -N 100 split; do
   arr=($(echo $split | grep -o .))
   ((i=i%100)); ((i++==0)) && wait
   handle_split "${arr[@]}" &
done < "filename.txt"

但是这种使用数组的实现甚至比简单的 for 循环还要慢。

while read -N 1 char; do
    :
done < "filename.txt"

GNU 或 BSD awk 可能是一个不错的选择:

awk 'BEGIN {FS=""}
  {for(i=1;i<=NF;i++) a[$i]++}
  END {for(i=0;i<10;i++) for(j=0;j<a[i];j++) printf "%d", i}' file

应该是你想要的。解释:BEGIN 块中的 FS="" 表示文件中的每个字符都是一个单独的字段。 {for(i=1;i<=NF;i++) a[$i]++} 块循环遍历所有字段(1 到 NF),并且对于每个字段,它都会递增 a 数组的 10 个单元格之一。 END 块在 END 处执行,它打印每个数字 d 的次数与 a[d] 的次数相同,按数字的递增顺序打印。

请注意,这不会打印最终换行符。如果您需要一个,请在该块的末尾添加 ; print ""

END {for(i=0;i<10;i++) for(j=0;j<a[i];j++) printf "%d", i; print ""}

当然,结果是多余的,您可能更喜欢更紧凑的形式,例如,每个字符一行,有两个字段:字符和出现次数:

awk 'BEGIN {FS=""}
  {for(i=1;i<=NF;i++) a[$i]++}
  END {for(i in a) printf "%s %d\n", i, a[i]}' file

刚刚在 3.6 GHz Intel Core i7 上测试了最后一个,输入为 1.4GB:2m38.480s。