我有一个文本文件,每行包含一些单词,例如:
stackoverflow coding programming
tag question badges
我必须对每一行进行排序并保留行的顺序。例如,对于上面的示例,输出应为:
coding programming stackoverflow
badges question tag
到目前为止,我的解决方案是创建一个临时文件,其中所有行都已排序。 bash脚本如下所示:
FILE_TMP=$FILE".tmp"
while read line
do
echo $line | xargs -n1 | sort | xargs >>$FILE_TMP
done < $FILE
mv $FILE_TMP $FILE
它工作正常,但我不高兴我必须创建一个重复的文件,特别是因为文件很大。
所以,我的问题是有没有解决方法来排序文件的每一行?
谢谢,
答案 0 :(得分:3)
试试这个(如果文件没有空格分隔,你可能需要更改sed):
cat datafile.dat | while read line; do echo $line | sed 's/ /\n/g' | sort | gawk '{line=line " " $0} END {print line}' ; done
答案 1 :(得分:2)
如果Python是一个选项,使用fileinput模块的就地支持将非常容易
>>> import os
>>> import fileinput
>>> for line in fileinput.input('file.txt', inplace=1):
... line = line.rstrip(os.linesep)
... print(' '.join(sorted(line.split())))
...
答案 2 :(得分:1)
您可以编写文本编辑器(例如vim或emacs)来编写脚本&#34;就位#34;但是这不会真正帮助您避免使用临时文件,因为文本编辑器将在内部使用临时文件。
如果你真正的问题是它运行缓慢,那可能是因为它为源文件中的每一行产生了3个不同的进程。您可以通过使用像perl这样的脚本语言来解决这个问题,这种语言可以通过文件排序行而不会产生任何其他进程。您还有一个额外的输出文件。
答案 3 :(得分:1)
接受的答案有点慢。试试这个:
awk ' {split( $0, a, " " ); asort( a ); for( i = 1; i <= length(a); i++ ) printf( "%s ", a[i] ); printf( "\n" ); }' input >output
注意:你的awk必须是GNU,以便有asort()。
答案 4 :(得分:0)
我认为以下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这样的东西。
答案 5 :(得分:0)
实际上,针对此问题的任何“合理”解决方案都会将新内容写入新的临时文件,然后重命名。甚至像perl“就地”处理(perl -pi...
)或文本编辑器这样的事情实际上也是如此。如果你想真正到位,写入相同的物理磁盘位置,可以完成(新内容占用与旧版本完全相同的空间),但是it's rather painful。< / p>
您可以将代码从this answer编译为overwrite
可执行文件,然后运行
(警告:这很危险,请先备份您的文件!)
while read line ; do echo $line | xargs -n1 | sort | xargs ; done < f | ./overwrite f
这是相当脆弱的,例如,您应该绝对确定执行脚本的排序不会弄乱空白字符(DOS换行符和连续空白?),脚本必须吐出相同的数量(或当它吃的时候每行的字节数。