Linux 使用shell对行的条目进行排序
考虑以下输入和输出:Linux 使用shell对行的条目进行排序,linux,bash,shell,unix,sorting,Linux,Bash,Shell,Unix,Sorting,考虑以下输入和输出: 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 是否存在不涉及编程语言(除shell脚本本身外)的UNIX程序组合,可以比以下方法更快地对文件每行中的条目进行排序: while read line; do tr ' ' '\n' <<< ${line} | sort | tr '\n' ' ' echo ""
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
是否存在不涉及编程语言(除shell脚本本身外)的UNIX程序组合,可以比以下方法更快地对文件每行中的条目进行排序:
while read line; do
tr ' ' '\n' <<< ${line} | sort | tr '\n' ' '
echo ""
done < infile > outfile
我的意思是,我能够创建一个小的cpp/python/awk/。。。程序可以这样做,但这与使用常用的一行程序神奇地解决问题不同
编辑:
我肯定加了太多的文字,而不是简单地问我想要什么;坦率地说,我想确认是否有任何UNIX程序/使用管道、fors、whiles等的程序组合。。。能够在一行中对条目进行排序,但没有与上述一种解决方案相同的开销
我知道我可能会在一种编程语言(如perl、awk、python)中做一些令人讨厌的工作,但实际上我正在寻找一种UNIX程序的组合,它不涉及这些语言解释器。从答案中,我必须得出结论,没有这样的内联排序工具,我非常感谢我得到的解决方案——主要是非常简洁的Perl one liner
然而,我并不真正理解为什么我发布的Bash方法会有如此多的开销。这真的是由于大量的上下文切换,还是仅仅是来回翻译输入和排序的开销
我似乎无法理解这些步骤中的哪一个会使执行速度减慢这么多。对文件中的条目进行排序需要几分钟的时间,每行大约500k行,每行大约30个值。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个进程。进程创建非常昂贵。Perl可以作为一行Unix/Linux命令很好地完成这项工作:
perl -n -e "print join ' ', sort{a<=>b} split ' '" < input.txt > output.txt
#!awk -f
{
baz = 0
PROCINFO["sorted_in"] = "@val_num_asc"
split($0, foo)
for (bar in foo)
$++baz = foo[bar]
}
1
这是一种过时的Perl,在a和b之前没有美元,这使得命令在Windows和bash shell中都能正常运行。如果将美元与bash一起使用,则必须使用反斜杠转义,或者必须反转单引号和双引号
请注意,您试图在命令、编程语言和程序之间划分的差别非常小。Bash是一种编程语言。Perl当然可以用作shell。两者都是命令
脚本运行缓慢的原因是它在每个循环迭代中产生3个进程。进程创建非常昂贵
#!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
结果
1 2 3 4 5
2 4 5
1 2 4 6
这个问题比看起来更微妙。你似乎在问是否有一种更快的方式来执行排序,你得到了很多优雅!使用Perl和awk等进行回答。但您的问题似乎是,是否可以使用shell内置程序进行更快的排序,对此,答案是否定的 显然,sort不是一个shell内置函数,tr也不是。没有一个内置函数可以实现sort的功能,并且可能替代tr的内置函数不太可能在这里对您有所帮助。操作bash的IFS变量来删除对tr的调用与使用tr一样需要大量的工作
就个人而言,我会选择Perl。请注意,如果您的数据集很大或很时髦,您可以选择使用sort pragma更改Perls默认排序算法。我不知道;我不认为你需要它来排序一个整数文件,但也许这只是你的一个例子 这个问题比看起来更微妙。你似乎在问是否有一种更快的方式来执行排序,你得到了很多优雅!使用Perl和awk等进行回答。但您的问题似乎是,是否可以使用shell内置程序进行更快的排序,对此,答案是否定的 显然,sort不是一个shell内置函数,tr也不是。没有一个内置函数可以实现sort的功能,并且可能替代tr的内置函数不太可能在这里对您有所帮助。操作bash的IFS变量来删除对tr的调用与使用tr一样需要大量的工作
就个人而言,我会选择Perl。请注意,如果您的数据集很大或很时髦,您可以选择使用sort pragma更改Perls默认排序算法。我不知道;我不认为你需要它来排序一个整数文件,但也许这只是你的一个例子 它不是一个非常明确的单行程序,但是您可以只使用内置的shell命令对一行进行排序,但是对于短行,它可能比反复调用要快 g外部功能
#!/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
它不是一个非常明确的单行程序,但是您可以只使用内置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
与其转义美元符号,为什么不在perl脚本周围使用单引号,而在脚本内的字符串使用双引号呢?@Barmar当然可以。我试图尽可能地保持两者的相似性。或者,在Unix上,简单地反转单引号和双引号:perl-n-e“print join,sort{$a$b}split”