考虑以下输入和输出:
infile | outfile
1 3 5 2 4 | 1 2 3 4 5
2 4 5 | 2 4 5
4 6 2 1 | 1 2 4 6
是否存在任何组合的UNIX程序,不涉及编程语言 - 除了shell脚本本身之外的其他任何东西 - 对每行中的条目进行排序文件比以下方法更快:
while read line; do
tr ' ' '\n' <<< ${line} | sort | tr '\n' ' '
echo ""
done < infile > outfile
我的意思是,我可以创建一个小cpp/python/awk/...
程序,但这与使用通常的 one-liners 来神奇地解决问题是不一样的。
修改
我必须添加太多文字,而不是简单地问我想要什么;直截了当地,我想确认是否有任何UNIX程序/ 程序组合(使用管道,fors,whiles,...)能够对一行中的条目进行排序,但没有像上面有一个解决方案。
我知道我可以用编程语言来完成讨厌的工作,比如perl,awk,python,但我实际上是在寻找一个不涉及这些语言解释器的UNIX程序组合。从答案中,我必须得出结论,没有这样的inline sort
工具,我非常感谢我得到的解决方案 - 主要是非常简洁的Perl单线程。
然而,我并不真正理解我发布的Bash方法上有如此多开销的原因。这真的是由于大量的上下文切换,还是仅仅是为了对输入进行翻译和排序的开销?
我似乎无法理解这些步骤中的哪一步会减慢执行速度。使用~500k行对文件中的条目进行排序需要几分钟,每行约30个值。
答案 0 :(得分:2)
Perl可以很好地完成单行Unix / Linux命令:
perl -n -e "print join ' ', sort{a<=>b} split ' '" < input.txt > output.txt
这是“古老的”Perl,在a
和b
之前没有美元,它允许命令在Windows和bash shell中正常运行。如果您将美元与bash一起使用,则必须使用反斜杠进行转义,或者必须反转单引号和双引号。
请注意,您尝试在命令,编程语言和程序之间绘制的区别非常薄。 Bash是一种编程语言。 Perl当然可以用作shell。两者都是命令。
脚本运行缓慢的原因是它每次循环迭代产生3个进程。流程创建非常昂贵。
答案 1 :(得分:1)
#!awk -f
{
baz = 0
PROCINFO["sorted_in"] = "@val_num_asc"
split($0, foo)
for (bar in foo)
$++baz = foo[bar]
}
1
结果
1 2 3 4 5 2 4 5 1 2 4 6
答案 2 :(得分:1)
问题比看起来更微妙。您似乎在询问是否有更快的方式来执行排序,并且您通过Perl和awk等获得了很多(优雅!)答案。但你的问题似乎是你是否可以使用shell 内置插件进行更快的排序,为此,答案是否定的。
显然,sort不是内置的shell,也不是tr。没有内置功能可以做什么,并且可能替代“tr”的内置函数不太可能在这里帮助你(比如说要操作bash的IFS变量需要花费太多工作来删除对tr的调用只是与tr)一起生活。
就个人而言,我会选择Perl。请注意,如果您的数据集很大或很时髦,您可以选择使用sort pragma更改Perls默认排序算法。我不认为你需要它来整理整数文件,但也许这只是你的一个例子。
答案 3 :(得分:0)
它不漂亮(绝对不是1-liner),但你可以只使用内置shell命令对行进行排序,但是对于短行,它可能比重复调用外部函数更快。
#!/bin/sh
sortline(){
for x in $@;do
[ ! "$FIRST" ] && FIRST=t && set --
i=0
while [ $i -le $# ];do
[ $x -lt $((${@:$((i+1)):1})) ] && break || i=$((i+1))
done
set -- ${@:1:$i} $x ${@:$((i+1)):$(($#-$i))}
done
echo $@
}
while read LINE || [ "$LINE" ];do
sortline $LINE
done <$1 >$2
编辑:顺便说一下这是一个选择排序算法,以防有人想知道
Edit2:这仅用于数值,对于你需要使用某些比较的字符串,如[ "$x" -lt "${@:$((i+1)):1}" ]
(未选中),但是我将这个C程序用于字符串(我只称它为qsort),但它可以在argv上使用atoi进行修改:
#include <stdlib.h>
#include <string.h>
static inline int cmp(const void *a, const void *b){
return strcmp(*(const char **)a, *(const char **)b);
}
int main(int argc, char *argv[]){
qsort(++argv, --argc, sizeof(char *), cmp);
while (argc){
write(1,argv[0],strlen(argv[0]));
write(1,(--argc && argv++)?"\t":"\n",1);
}
}