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”output.txt。与其转义美元符号,为什么不在perl脚本周围使用单引号,在脚本内部使用双引号?@Barmar当然可以。或者,在Unix上,简单地反转单引号和双引号:perl-n-e'print join,sort{$a$b}split'output.txt。似乎没有响应者完全理解您的问题:您的代码适用于10以下的数字。如果在一行中添加11,则无法正确排序。如果需要数字排序,请使用sort-n。创造性地使用可以保存一些周期,但这也取决于输入数据的类型。似乎没有响应者完全阅读/理解您的问题:您的代码适用于10以下的数字。如果在一行中添加11,则无法正确排序。如果您需要数字排序,请使用sort-n。您可以创造性地使用保存一些循环,但这也取决于输入数据的类型。我没有命名sort或tr内置;我只是想把普通的UNIX文本处理工具与perl、ipython、awk等语言解释器/shell区别开来。实际上我并不介意这个工具,我只是想找一些简单一点的东西,比如用fors/pipes链接工具,或者用Perl实现非常优雅的解决方案。当然,有些东西并不像我的方法那样耗时——我还没有弄明白为什么它如此之慢。@Rubens它之所以如此之慢,是因为它将整个数据读取了4次read,tr,sort,tr。它还为每一行创建子shell、管道和许多进程。我没有命名sort或tr内置程序;我只是想把普通的UNIX文本处理工具与perl、ipython、awk等语言解释器/shell区别开来。实际上我并不介意这个工具,我只是想找一些简单一点的东西,比如用fors/pipes链接工具,或者用Perl实现非常优雅的解决方案。当然,有些东西并不像我的方法那样耗时——我还没有弄明白为什么它如此之慢。@Rubens它之所以如此之慢,是因为它将整个数据读取了4次read,tr,sort,tr。它还为每一行创建了子shell,管道和许多进程。作为一个巡更力,它是非凡的+1;作为一个建议的答案,这是令人震惊的-1。Net-不投票。@JonathanLeffler-嗯,听起来像是一个有趣的挑战,但它只比调用sort更快,每行少于10个字段。如果你认为这是骇人听闻的,作为一个巡演,它是非凡的+1;作为一个建议的答案,这是令人震惊的-1。Net-不投票。@JonathanLeffler-嗯,听起来像是一个有趣的挑战,但它只比调用sort更快,每行少于10个字段。如果你觉得这太可怕了,看看吧