连接文本文件,用新行分隔它们

问题描述 投票:0回答:4

我在目录中只有100多个文本文件,作为一个简单的数据库,每行包含一个记录。总的来说,这些文件总计大约25GB。但是,记录没有按字母顺序排序,并且有很多重复,所以为了使用像sort -u这样的所有~100个文本文件的内容进行分类,我首先尝试将所有这些文件组合成一个大的文本文件。一个简单的cat将是不合适的,因为100个文本文件的开头和结尾不包含新行,(据我的理解)这将导致文件中的最后一个记录与下一个文件的第一个记录合并。

What solutions are there that would allow me to concatenate my text files while ensuring there is a single new line character separating them?

database bash text concatenation text-files
4个回答
4
投票

一个简单的

sort -u *.db > uniquified # adjust glob as needed

应该这样做;如有必要,sort将在文件之间插入换行符。

cat *.db | sort -u

是一个经典的UUoC和文件缺乏尾随换行的故障并不是唯一的问题。

话虽如此,25GB可能不适合你的RAM,所以sort最终会创建临时文件。对四个或五个组中的文件进行排序可能会更快,然后合并结果。这可以更好地利用大量重复数据。但我只是试验这个简单的命令真的需要花费过多的时间。

即便如此,单独排序文件可能更慢;通常最好的办法是在每次调用sort时最大化你的内存资源。例如,您可以使用带有xargs选项的-n将文件列表分成几组,每组包含几十个文件。一旦您对每个组进行了排序,您就可以使用sort -m来合并已排序的临时组。

关于如何提高分拣速度的几点注意事项:

  1. 如果您不需要区域设置感知的字母数据排序,请使用LC_COLLATE=C sort。这通常会使排序增加三倍或四倍。
  2. 避免将RAM磁盘用于临时空间。 (在许多Linux发行版中,/tmp是一个RAM磁盘。)由于sort在RAM耗尽时使用临时磁盘,因此将临时磁盘放入RAMdisk会产生相反的效果。出于同样的原因,不要将自己的临时输出文件放在/tmp中。 /var/tmp应该是真正的磁盘;更好的是,如果可能的话,使用第二个磁盘驱动器(当然不是慢速USB驱动器)。
  3. 通过关闭掉掉交换,避免在进行排序时过度交换机器: sudo swapoff -a 之后你可以重新打开它,虽然我个人经常这样运行我的机器,因为它可以避免在内存压力下潜入完全无响应。
  4. 理想的是调整-S,以便sort尽可能多地使用内存,并通过排序适合该内存量的块来避免使用内部临时值。 (合并排序的块比排序快得多,并且它可以顺序读取和写入而无需额外的磁盘空间。)您可能需要进行一些实验才能找到一个好的块大小。

2
投票

我会告诉你通过连接所有输入文件并在中间插入一个新行来创建该文件:

out=newfile.txt
rm -f "$out"
for f in *.txt
do
    cat "$f" >> "$out"
    echo >> "$out"
done

现在你可以对它进行排序。或者删除空行,以防您认为可能有一些输入文件末尾有新行。


2
投票

你可以使用awk。

$ od -t x1 file1
0000000 72 65 63 6f 72 64 31 0a 72 65 63 6f 72 64 32
0000017
$ od -t x1 file2
0000000 72 65 63 6f 72 64 31 0a 72 65 63 6f 72 64 32 0a
0000020 72 65 63 6f 72 64 33
0000027
$ awk 1 file1 file2
record1
record2
record1
record2
record3

1是awk脚本,这意味着打印所有记录


1
投票

sort *应该是您所需要的全部内容,但万一您确实需要将新行添加到文件内容以供后续工具处理,以下是如何执行此操作:

$ ls
file1  file2
$ cat file1
foo$
$ cat file2
bar$
$ cat file1 file2
foobar$

$ find . -type f -exec sh -c '(cat {}; printf "\\n")' \;
foo
bar

当然,假设您的cat可以处理不以换行符结尾的文件!

© www.soinside.com 2019 - 2024. All rights reserved.