如何使用awk按第3列排序

问题描述 投票:0回答:10

我有一个像这样的文件(user.csv)

ip,hostname,user,group,encryption,aduser,adattr

想要打印按用户排序的所有列,

我试过

awk -F ":" '{print|"$3 sort -n"}' user.csv
,没用。

awk
10个回答
252
投票

sort
怎么样。

sort -t, -nk3 user.csv

哪里

  • -t,
    - 将分隔符定义为
    ,

  • -n
    - 为您提供数字排序。自从您将其添加到您的 试图。如果您的用户字段只是文本,那么您不需要它。

  • -k3
    - 定义字段(键)。 user 是第三个字段。


32
投票
  1. 使用awk将用户ID放在前面。
  2. 排序
  3. 使用 sed 删除重复的用户 ID,假设用户 ID 不包含任何空格。

    awk -F, '{ print $3, $0 }' user.csv | sort | sed 's/^.* //'
    

19
投票

鉴于最初的问题是如何使用

awk
,前 7 个答案中的每一个都使用
sort
,而且这是 Google 上的热门搜索,以下是如何使用
awk

带有标题的示例 net.csv 文件:

ip,hostname,user,group,encryption,aduser,adattr
192.168.0.1,gw,router,router,-,-,-
192.168.0.2,server,admin,admin,-,-,-
192.168.0.3,ws-03,user,user,-,-,-
192.168.0.4,ws-04,user,user,-,-,-

sort.awk

#!/usr/bin/env -S awk -f
#
# original source:
# https://stackoverflow.com/a/65768883/586229
#
# Usage:
#   awk -f sort.awk [-F<field separator>] [-v h=HAS_HEADER] [-v f=COLUMN_TO_SORT_BY] INPUT_FILE
# Examples:
#   awk -f sort.awk -F, -v h=1 -v f=1 input.csv > output.csv
#   cat input.txt | awk -f sort.awk | tee -a output.txt

# for each line
{
    if (h && NR == 0) {
        print $0
    } else {
        a[NR-h]=$0 ""
        s[NR-h]=$f ""
    }
}

END {
    isort(s, a, NR-h);
    for (i = 1; i <= NR-h; i++) {
        print a[i]
    }
}

# insertion sort of A[1..n]
function isort(S, A, n, i, j) {
    for (i = 2; i <= n; i++) {
        hs = S[j=i]
        ha = A[j=i]
        while (S[j-1] > hs) {
            j--;
            S[j+1] = S[j]
            A[j+1] = A[j]
        }
        S[j] = hs
        A[j] = ha
    }
}

使用方法:
请参阅脚本中的标题。

更新:请参阅我的其他答案,了解使用快速排序而不是插入排序可加速 100 倍。


12
投票

您可以选择分隔符,在本例中我选择了冒号并打印第一列,按字母顺序排序:

awk -F\: '{print $1|"sort -u"}' /etc/passwd

10
投票
awk -F, '{ print $3, $0 }' user.csv | sort -nk2 

以及相反的顺序

awk -F, '{ print $3, $0 }' user.csv | sort -nrk2 

6
投票

试试这个-

awk '{print $0|"sort -t',' -nk3 "}' user.csv

sort -t',' -nk3 user.csv

4
投票
awk -F "," '{print $0}' user.csv | sort -nk3 -t ','

这应该有效


3
投票

为了从排序中排除第一行(标题),我将其分成两个缓冲区。

df | awk 'BEGIN{header=""; $body=""} { if(NR==1){header=$0}else{body=body"\n"$0}} END{print header; print body|"sort -nk3"}'

2
投票

GNU

awk
:

awk -F ',' '{ a[$3]=$0 } END{ PROCINFO["sorted_in"]="@ind_str_asc"; for(i in a) print a[i] }' file

请参阅 8.1.6 使用 gawk 的预定义数组扫描顺序了解更多排序算法。


0
投票

我正在使用 mawk 运行 Linux (Ubuntu):

tmp$ awk -W version
mawk 1.3.4 20200120
Copyright 2008-2019,2020, Thomas E. Dickey
Copyright 1991-1996,2014, Michael D. Brennan

random-funcs:       srandom/random
regex-funcs:        internal
compiled limits:
sprintf buffer      8192
maximum-integer     2147483647

mawk(和 gawk)有一个选项可以将

print
的输出重定向到命令。来自
man awk
9章。输入和输出:

可以通过附加 > file、>> file 或 | 将 print 和 printf 的输出重定向到文件或命令。命令到打印语句的末尾。 重定向仅打开文件或命令一次,后续重定向附加到已经打开的流。

下面您将找到一个简单的示例,如何使用

|
将所需记录传递给外部程序,从而完成艰苦的工作。这也很好地将所有内容封装在一个 awk 文件中并减少了命令行混乱:

tmp$ cat input.csv 
alpha,num
D,4
B,2
A,1
E,5
F,10
C,3
tmp$ cat sort.awk 
# print header line
/^alpha,num/ {
    print
}

# all other lines are data lines that should be sorted
!/^alpha,num/ {
    print | "sort --field-separator=, --key=2 --numeric-sort"
}
tmp$ awk -f sort.awk input.csv 
alpha,num
A,1
B,2
C,3
D,4
E,5
F,10

有关

man sort
选项的详细信息,请参阅
sort

-t, --field-separator=SEP
       use SEP instead of non-blank to blank transition
-k, --key=KEYDEF
       sort via a key; KEYDEF gives location and type
-n, --numeric-sort
       compare according to string numerical value
© www.soinside.com 2019 - 2024. All rights reserved.