繁体   English   中英

Bash 按列对列表进行排序

[英]Bash Sorting a List by Columns

我正在对第 2 列进行反向排序。至于第 1 列,如果多行具有相同的 $2 值,我希望它们以相反的顺序排序。 目前,我已将此列表存储在 bash 脚本中的一个变量中。 有没有sed或者awk function可以用?

例如,我现在的 output 是:

123, 3
124, 3
12345, 2
898, 1
1010, 1

我想要的是:

124, 3
123, 3
12345, 2
1010, 1
898, 1

这不是一个简单的awk脚本,但也不难。 您只需使用下面的数组a[]来存储第二个字段的相等值的第一个字段的值。 如果设置了last (例如,不是第一条记录)并且第二个字段发生变化,则您 output 当前数组并重置数组(即规则 1)。

在规则 2 中,您只需扫描现有数组并按顺序将当前第一个字段插入数组中。 您保留第二个字段的last值,以便知道它何时更改。 您使用END规则来 output 最后一组值,例如

awk -F, '
    last && $2 != last {
        for (i=1; i<=n; i++)
            print a[i]", "last;
        delete a
        n = 0
    }
    {
        swapped=0
        for (i=1; i<=n; i++)
            if ($1 > a[i]) {
                swapped=1
                for (j=n+1; j>i; j--)
                    a[j]=a[j-1]
                a[i]=$1
            }
        if (!swapped)
            a[++n]=$1
        else
            n++
        last=$2
    }
END {
    for (i=1; i<=n; i++)
        print a[i]", "last
    }
' file

swapped标志只是告诉您当前的第一个字段是在现有元素之前插入到数组中( swapped == 1 )还是只是在末尾添加( swapped == 0 )。

示例使用/输出

使用名为file的文件中的示例文件,您可以简单地更改为包含它的目录, select 上面的脚本用鼠标(将文件名更改为您的文件名)然后鼠标中键将脚本粘贴到终端中,例如

$ awk -F, '
>     last && $2 != last {
>         for (i=1; i<=n; i++)
>             print a[i]", "last;
>         delete a
>         n = 0
>     }
>     {
>         swapped=0
>         for (i=1; i<=n; i++)
>             if ($1 > a[i]) {
>                 swapped=1
>                 for (j=n+1; j>i; j--)
>                     a[j]=a[j-1]
>                 a[i]=$1
>             }
>         if (!swapped)
>             a[++n]=$1
>         else
>             n++
>         last=$2
>     }
> END {
>     for (i=1; i<=n; i++)
>         print a[i]", "last
>     }
> ' file
124,  3
123,  3
12345,  2
1010,  1
898,  1

检查一下,如果您有任何问题,请告诉我。

使用 Perl 单行和sort的组合。 一行代码将,定界符转换为制表符(并返回)。 sort使用-r选项进行反向排序,使用-g选项进行数字排序。 选项-kN,N指定仅按字段N排序,这里是第 2 个,然后是第 1 个字段。

perl -pe 's/, /\t/' in_file | sort -k2,2gr -k1,1gr | perl -pe 's/\t/, /' > out_file

例如:

创建示例输入文件:

cat > foo <<EOF
123, 3
124, 3
12345, 2
898, 1
1010, 1
EOF

运行命令:

cat foo | perl -pe 's/, /\t/' | sort -k2,2gr -k1,1gr | perl -pe 's/\t/, /' 

Output:

124, 3
123, 3
12345, 2
1010, 1
898, 1

Perl 一行代码使用这些命令行标志:
-e :告诉 Perl 查找内联代码,而不是在文件中。
-p :一次循环输入一行,默认情况下将其分配给$_ 在每次循环迭代后添加print $_

也可以看看:
perldoc perlrun :如何执行 Perl 解释器:命令行开关
perldoc perlrequick : Perl 正则表达式快速入门

还有awk ,你可以试试这个:

awk 'BEGIN{RS=""; OFS=FS="\n"} {tmp2 = $2; $2 = $1; $1 = tmp2; tmp5=$5; $5=$4; $4=tmp5}1' file
124, 3
123, 3
12345, 2
1010, 1
898, 1

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM