我有一个文本文件,每行包含一些单词,例如:
stackoverflow coding programming tag question badges
我必须对每一行进行sorting并保留行的顺序。 例如,对于上面的例子,输出应该是:
coding programming stackoverflow badges question tag
我的解决scheme,直到现在是创build一个临时文件,其中所有行都sorting。 bash脚本如下所示:
FILE_TMP=$FILE".tmp" while read line do echo $line | xargs -n1 | sort | xargs >>$FILE_TMP done < $FILE mv $FILE_TMP $FILE
它工作正常,但我不高兴我必须创build一个重复的文件,特别是因为文件很大。
所以,我的问题是有任何解决scheme来sorting文件的每一行?
谢谢,
试试这个(如果文件不是空格分隔的,你可能必须改变sed):
cat datafile.dat | while read line; do echo $line | sed 's/ /\n/g' | sort | gawk '{line=line " " $0} END {print line}' ; done
你可以编写一个文本编辑器(例如vim或emacs)来“做到”,但是这并不能帮助你避免使用临时文件,因为文本编辑器将在内部使用临时文件。
如果真正的问题是运行速度慢,那可能是因为它在源文件中为每行产生了3个不同的进程。 你可以通过使用像perl这样的脚本语言来解决这个问题,这个脚本语言可以通过文件的排序行而不会产生任何额外的进程。 你仍然有一个额外的文件输出。
如果Python是一个选项,那么使用fileinput模块的in-place支持将会非常容易
>>> import os >>> import fileinput >>> for line in fileinput.input('file.txt', inplace=1): ... line = line.rstrip(os.linesep) ... print(' '.join(sorted(line.split()))) ...
我认为以下awk善良应该做的工作:
prompt$ cat foo.awk { n = split($0, words) do { change_occured = 0 for (idx = 1; idx <= n; ++idx) { if (words[idx] > words[idx + 1]) { t = words[idx] words[idx] = words[idx + 1] words[idx + 1] = t change_occured = 1 } } } while (change_occured != 0) for (idx in words) { printf("%s ", words[idx]) } split("", array) print "" } prompt$ awk -f foo.awk <<EOF heredoc> stackoverflow coding programming heredoc> tag question badges heredoc> EOF coding programming stackoverflow badges question tag
编辑注意,这不是一个到位的编辑。 它起着从stdin到stdout的过滤器的作用。 你可以使用awk,但是读写文件感觉“笨重”。 如果你真的想避免临时文件,使用像Perl的东西。
实际上,针对这个问题的任何“合理的”解决方案都会将新内容写入新的临时文件,然后重新命名。 即使像perl“就地”处理( perl -pi...
)或文本编辑器这样的东西实际上是这样做的。 如果你想真的到位 ,写入相同的物理磁盘位置,可以完成(新的内容占据与旧的完全相同的空间),但是这是相当痛苦的 。
您可以将此答案中的代码编译为overwrite
可执行文件,然后运行(警告:这很危险,请先备份文件!)
while read line ; do echo $line | xargs -n1 | sort | xargs ; done < f | ./overwrite f
这是相当脆弱的,例如,你应该确保脚本的排序不会混淆空白字符(关于DOS换行符和连续的空白字符?),脚本必须吐出相同数量(或更少)的它吃的每行字节数。