从文本文件中分割字符串的快速方法?

从文本文件中分割字符串的快速方法?

我有两个文本文件:string.txt 和 lengths.txt

字符串.txt:

abcdefghijklmnopqrstuvwxyz

长度.txt

5
4
10
7

我想获取文件

>Entry_1
abcde
>Entry_2
fghi
>Entry_3
jklmnopqrs
>Entry_4
tuvwxyz

我正在处理大约 28,000 个条目,它们的字符数在 200 到 56,000 之间。

目前,我正在使用:

start=1
end=0
i=0
while read read_l
do
    let i=i+1
    let end=end+read_l
    echo -e ">Entry_$i" >>outfile.txt
    echo "$(cut -c$start-$end String.txt)" >>outfile.txt
    let start=start+read_l
    echo $i
done <lengths.txt

但这是非常低效的。还有更好的想法吗?

答案1

一般来说,你不想使用 shell 循环来处理文本。在这里,我会使用perl

$ perl -lpe 'read STDIN,$_,$_; print ">Entry_" . ++$n' lengths.txt < string.txt
>Entry_1
abcde
>Entry_2
fghi
>Entry_3
jklmnopqrs
>Entry_4
tuvwxyz

那是命令,该命令(使用缓冲,比read一次读取一个字节(或常规文件的几个字节)的 shell 命令更有效)两个文件仅读取一次(不会将它们完全存储在内存中),所以将比在 shell 循环中运行外部命令的解决方案效率高几个数量级。

-C如果这些数字应该是当前区域设置中的字符数而不是字节数,请添加该选项。对于示例中的 ASCII 字符,这不会产生任何区别)。

答案2

你可以做

{
  while read l<&3; do
    {
      head -c"$l"
      echo
    } 3<&-
  done 3<lengths.txt
} <String.txt

它需要一些解释:

主要思想是使用{ head ; } <file并源自被低估的@mikeserv回答。然而,在这种情况下,我们需要使用许多heads,因此while引入了循环并对文件描述符进行了一些调整,以便传递到head两个文件的输入(文件String.txt作为要处理的主文件,行length.txt作为选项的参数-c) 。这个想法是,速度上的好处应该来自于不需要每次调用类似或 之String.txt类的命令时都进行搜索。只是在每次迭代后打印换行符。headcutecho

它的速度有多快(如果有的话)以及>Entry_i在行之间添加内容作为练习。

答案3

bash,版本 4

mapfile -t lengths <lengths.txt
string=$(< String.txt)
i=0 
n=0
for len in "${lengths[@]}"; do
    echo ">Entry_$((++n))"
    echo "${string:i:len}"
    ((i+=len))
done

输出

>Entry_1
abcde
>Entry_2
fghi
>Entry_3
jklmnopqrs
>Entry_4
tuvwxyz

答案4

关于什么awk

创建一个使用以下代码调用的文件process.awk

function idx(i1, v1, i2, v2)
{
     # numerical index comparison, ascending order
     return (i1 - i2)
}
FNR==NR { a[FNR]=$0; next }
{ i=1;PROCINFO["sorted_in"] = "idx";
        for (j in a) {
                print ">Entry"j;
                ms=substr($0, i,a[j])
                print ms
                i=i+length(ms)
        }
}

保存并执行awk -f process.awk lengths.txt string.txt

相关内容