有没有比使用 while 循环更有效的方法来创建每行都有重复文本的文件?(100万行+)



我需要创建一个文本文件,该文件只包含每行上的点符号".",重复,直到达到变量中存储的特定行数。我现在使用 while 循环,但那些带有点的文件需要大约 0.5-5 百万行。因此,它需要的时间比我希望的要长一些。以下是我当前的代码:

j=0
while [[ $j != $length ]] 
do
echo "." >> $file
((j++))
done

所以我的问题是:除了使用 while 循环之外,是否有更有效的方法来创建具有 x 行数的文件,每个行都包含相同的字符(或字符串)重复?

谢谢

您可以使用yeshead

yes . | head -n "$length" > "$file"

这应该比重复打开和关闭文件以一次写入两个字节要快得多。

使用dd写入输出文件(耗时不到 2 秒)

time yes . | dd of=dotbig.txt count=1024 bs=1048576 iflag=fullblock
1024+0 records in
1024+0 records out
1073741824 bytes (1.1 GB, 1.0 GiB) copied, 1.76116 s, 610 MB/s
real    0m1.814s
user    0m0.076s
sys     0m0.686s

行数

wc -l dotbig.txt
536870912 dotbig.txt

内容示例:

head -n 3 dotbig.txt ; tail -n 3 dotbig.txt
.
.
.
.
.
.

此代码中最耗费资源的部分是重定向 (echo '.' > $file)。要解决此问题,您需要"构建"一个字符串并仅重定向到$file一次,而不是$length次。

j=0
while [[ $j != $length ]]
do
builder=${builder}.
done
echo "$builder" > $file

但是,您仍然处于一个循环中,这可能不是资源的最佳利用方式。为了解决这个问题,让我们从这个答案中得到灵感:

printf '.n%.0s' $(seq $length) > $file

请注意,这里我们使用$(seq $length)而不是{1..$length}因为如果长度为 10,bash 不会{1..$length}扩展到0 1 2 3 4 5 6 7 8 9 10(请参阅此问题)

如果仅仅是由于为循环中的每个命令启动新操作系统进程(对于每次通过循环)的开销,那么bash中的重复操作(例如,通过循环)总是会很慢。在这种情况下,在每次通过循环时打开和关闭输出文件会产生额外的开销。

您希望寻找一种解决方案,以限制需要创建/关闭的操作系统进程数(在这种情况下,限制打开/关闭输出文件的次数)。 会有很多选择,具体取决于您要使用的软件/工具/二进制文件。

一个awk想法:

awk -v len="${length}" 'BEGIN {for (i=1;i<=len;i++) print "."}' > newfile

虽然这确实使用了awk中的"循环",但我们只在bash级别查看单个操作系统进程,并且我们只打开/关闭输出文件一次。

这应该每次都会使文件大小加倍。 也许它比其他一些解决方案更有效,也许不是。 文件"b"的大小将继续加倍,直到加倍使其超过长度的大小。 当长度是 2 的幂时,我认为这将是非常有效的。

let n=2
let length=1000000
echo '.' > a
cat a a > b
rm a
while [[ $((n*2)) -le $length ]]; do
mv b a
cat a a > b
rm a 
let n=n*2
done
# do something here to fill out the remaining length-n lines

相关内容

  • 没有找到相关文章