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

use*_*532 12 linux shell-script

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

字符串.txt:

abcdefghijklmnopqrstuvwxyz
Run Code Online (Sandbox Code Playgroud)

长度.txt

5
4
10
7
Run Code Online (Sandbox Code Playgroud)

我要获取文件

>Entry_1
abcde
>Entry_2
fghi
>Entry_3
jklmnopqrs
>Entry_4
tuvwxyz
Run Code Online (Sandbox Code Playgroud)

我正在处理大约 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
Run Code Online (Sandbox Code Playgroud)

但它非常低效。有什么更好的想法吗?

Sté*_*las 8

通常,您不想使用 shell 循环来处理 text。在这里,我会使用perl

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

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

-C如果这些数字应该是当前语言环境中的字符数而不是字节数,则添加选项。对于示例中的 ASCII 字符,这不会有任何区别)。


jim*_*mij 7

你可以做

{
  while read l<&3; do
    {
      head -c"$l"
      echo
    } 3<&-
  done 3<lengths.txt
} <String.txt
Run Code Online (Sandbox Code Playgroud)

它需要一些解释:

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

它有多快(如果有的话)和在行>Entry_i之间添加作为练习。


gle*_*man 6

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
Run Code Online (Sandbox Code Playgroud)

输出

>Entry_1
abcde
>Entry_2
fghi
>Entry_3
jklmnopqrs
>Entry_4
tuvwxyz
Run Code Online (Sandbox Code Playgroud)