【发布时间】:2012-05-18 19:04:20
【问题描述】:
我想在文本文件中添加一行,以便对结果进行排序,文本文件最初是在其中排序的。例如:
cp file tmp; echo "new line" >> tmp; sort tmp > file; rm -f tmp
我真的很想不带临时文件和不带分号(改用管道?);使用sed 是可以接受的。这可能吗?如果可以,怎么做?
【问题讨论】:
我想在文本文件中添加一行,以便对结果进行排序,文本文件最初是在其中排序的。例如:
cp file tmp; echo "new line" >> tmp; sort tmp > file; rm -f tmp
我真的很想不带临时文件和不带分号(改用管道?);使用sed 是可以接受的。这可能吗?如果可以,怎么做?
【问题讨论】:
echo "New Line" | sort -o file - file
-o file 表示将结果写入文件(将任何输入文件作为输出文件是明确安全的)。 - 本身的意思是“读取标准输入”,其中包含新的信息行。末尾的file 表示“也阅读file”。这适用于大约 1978 年(至少)第 7 版 UNIX™ 起的任何 Unix 排序,甚至可能在此之前。没有临时文件或对其他实用程序的依赖。
鉴于单行已“排序”并且文件也已排序,您可以通过合并两个已排序的输入来加快处理速度:
echo "New Line" | sort -o file -m - file
这也适用于非常古老的排序命令。
【讨论】:
这是我能想到的最短的没有任何临时文件的班轮:
$ echo "something" >> file; sort file -o file
【讨论】:
sort 或许可以将所有数据保存在内存中。
是的,您需要同时使用或 comm 他们(如果他们已经预先排序)假设他们没有标签,这将为您节省排序(这可以产生临时文件和开销取决于文件大小)。
替代方案:
comm -3 file <(echo "new line") |tr -d '\t'
这可能是“最短的”:
sort -m file <(echo "new line")
【讨论】:
sort -m 选项很好,但需要注意的是,像这样的进程替换 (<(echo new line)) 是 bash 特定的(并不是真正必要的)。
您可以在没有任何分号和临时文件的情况下执行此操作,但可能需要依赖一些可能并非无处不在的实用程序(例如带有就地文件修改的 awk 或 perl)。
为什么不想使用临时文件或分号?
编辑:既然分号是可以的,那么如何:
val=$(cat file); { echo "$val"; echo "new line"; } | sort > file
【讨论】:
-T 选项。上面的答案避免了我很确定。在大多数情况下这很愚蠢,但我已经对在 sort 上执行过多 tmp IO 的大文件进行了 AB 分析。
大文件/性能:
将您的文件转换为具有单个索引列的 SQLite 数据库并进行查询。
或者自己重新实现一个基于文件的 B-tree 或者 hash map,SQLite 是如何实现索引的……
我认为不可能有效地插入已排序的文本文件:即使您进行二进制搜索,您仍然必须复制插入点之后的所有内容,并且磁盘操作将成为瓶颈:https://unix.stackexchange.com/questions/87772/add-lines-to-the-beginning-and-end-of-the-huge-file
对于搜索,sgrep 可能有效:https://askubuntu.com/questions/423886/efficiently-search-sorted-file/701237#701237
【讨论】: