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)
但它非常低效。有什么更好的想法吗?
通常,您不想使用 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 字符,这不会有任何区别)。
你可以做
{
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之间添加作为练习。
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)
| 归档时间: |
|
| 查看次数: |
1448 次 |
| 最近记录: |