使用awk并排序按ID字段对表进行排序

时间:2012-10-28 18:41:03

标签: unix sorting awk

我正在学习Unix,我想对此表进行排序:

Name:Alice,ID:2368,Hometown:columbus,bithday:03/11/1988
Name:Ted,ID:2368,Hometown:Portland,bithday:06-11-1992
Name:Mark,ID:2218,Hometown:Palo Alto,bithday:04-23-1984
Name:Xiao,ID:2571,hometown:Carson,bithday:07/06/1975
Name:Rain,ID:0264,hometown:little stone,bithday:11-09-1982
Name:Susan,ID:1261,Hometown:Menlo park,bithday:12-13-1989
Name:Zack,ID:1594,Hometown:columbus,bithday:02-04-1984

并将其格式化为:

Rain,0264,little stone,11-09-1982
Susan,1261,Menlo park,12-13-1989
Zack,1594,columbus,02-04-1984
Mark,2218,Palo Alto,04-23-1984
Alice,2368,columbus,03-11-1988
Ted,2368,Portland,06-11-1992
Xiao,2571,Carson,07-06-1975

我想过滤出键值对中的键(键:值),然后使用awk和sort按ID排序。

我会用什么命令来做这件事?

9 个答案:

答案 0 :(得分:3)

这很简单:

awk -F: '{gsub(/,[^:]*:/,",");print $2}' You_file| sort -t, -k 2,2n

测试如下:

> cat temp
Name:Alice,ID:2368,Hometown:columbus,bithday:03/11/1988
Name:Ted,ID:2368,Hometown:Portland,bithday:06-11-1992
Name:Mark,ID:2218,Hometown:Palo Alto,bithday:04-23-1984
Name:Xiao,ID:2571,hometown:Carson,bithday:07/06/1975
Name:Rain,ID:0264,hometown:little stone,bithday:11-09-1982
Name:Susan,ID:1261,Hometown:Menlo park,bithday:12-13-1989
Name:Zack,ID:1594,Hometown:columbus,bithday:02-04-1984
>

现在执行:

> awk -F: '{gsub(/,[^:]*:/,",");print $2}' temp | sort -t, -k 2,2n
Rain,0264,little stone,11-09-1982
Susan,1261,Menlo park,12-13-1989
Zack,1594,columbus,02-04-1984
Mark,2218,Palo Alto,04-23-1984
Alice,2368,columbus,03/11/1988
Ted,2368,Portland,06-11-1992
Xiao,2571,Carson,07/06/1975

答案 1 :(得分:2)

我花了一段时间才弄明白,直到我终于看到你的输入数据中的“生日”拼写错误。

你可以全力以赴,并将数据解析为实际数据:

awk -F, '
  BEGIN {
    fmt="%s,%s,%s,%s\n";
  }

  {
    for (i=1;i<=NF;i++) {           # walk through the fields...
      split($i,a,":");              # split each one at the colon, save to array
      v[tolower(a[1])]=a[2];        # need tolower() as "Hometown" is inconsistent
    }
    split(v["bithday"],b,/[-\/]/);  # regex here handles your inconsistent divider
    v["bithday"]=sprintf("%s-%s-%s",b[3],b[2],b[1]);
    printf(fmt,v["name"],v["id"],v["hometown"],v["bithday"]);
  }
' input.txt | sort -t, -k2

这会遍历每一行,用逗号分隔字段,将key = value组合存储在数组中,调整“bithday”格式并打印。 (请注意,我为您选择了更明智的日期格式。)

但是做一些简单的模式匹配可能更容易:

sed -Ene 's/^[[:alpha:]]+://;s/,[[:alpha:]]+:/,/g;s/([0-9]{2}).([0-9]{2}).([0-9]{4})$/\3-\2-\1/;p' input.txt \
| sort -t, -k2

这会产生相同的结果,但代码更少。如果您需要使用输入数据做更多有趣的事情,那么当然,awk是可行的方法。

哦,我的sed来自FreeBSD,所以它使用-E选项来获取ERE。如果您正在使用Linux或其他GNU sed提供程序,则可以将-E替换为-r

答案 2 :(得分:2)

使用grep查找值,粘贴以重新组合行,当然排序:

grep -oP '(?<=:).*?(,|$)' filename | paste -d "" - - - - | sort -n -t, -k2

假设值中没有逗号。

答案 3 :(得分:1)

我发现最简单的方法是使用awk重新格式化输出,并附加sort将使用的新列,然后再次使用awk来隐藏该列。

$ cat test.dat
Name:Alice,ID:2368,Hometown:columbus,bithday:03/11/1988
Name:Ted,ID:2368,Hometown:Portland,bithday:06-11-1992
Name:Mark,ID:2218,Hometown:Palo Alto,bithday:04-23-1984
Name:Xiao,ID:2571,hometown:Carson,bithday:07/06/1975
Name:Rain,ID:0264,hometown:little stone,bithday:11-09-1982
Name:Susan,ID:1261,Hometown:Menlo park,bithday:12-13-1989
Name:Zack,ID:1594,Hometown:columbus,bithday:02-04-1984

$ cat test.dat| awk -F, '{ gsub(/[a-zA-Z]+:/, ""); print $2,$0; }' | sort | awk '{ $1=""; print; }'
 Rain,0264,little stone,11-09-1982
 Susan,1261,Menlo park,12-13-1989
 Zack,1594,columbus,02-04-1984
 Mark,2218,Palo Alto,04-23-1984
 Alice,2368,columbus,03/11/1988
 Ted,2368,Portland,06-11-1992
 Xiao,2571,Carson,07/06/1975

-F用于指定分隔符(此处为,)。然后我们想删除列名(即任何字母后跟:),最后显示ID列和整个重写行。 然后我们使用sort,默认情况下假设排序键是第一列,再次awk只显示每行的第二部分。

编辑:给定城市中的空格,awk存在输出问题。为了简单起见,我只是重新分配了第一个变量(这是你想隐藏的列)并打印整行。

答案 4 :(得分:1)

一定有awk吗?如果不是:

  1. 使用Vim删除:%s/[a-z]*://gi
  2. 的关键字符串
  3. 使用排序来排序:sort -t , -k 2 file
  4. 如果AWK是必须的,那么我会想到this,排序没有丢失键 - 但@Aif给出的答案也很好。

    编辑:感谢@ Aif的正则表达式以及@ Ghoti的评论。现在Vim命令替换使用正则表达式和密钥案例和文本'不是'正如Yoda所说的那样。

答案 5 :(得分:1)

这是使用GNU awk的一种方式:

awk 'BEGIN { FS="[,:]"; OFS="," } { for (i=2; i<=NF; i+=2) printf (i!=NF) ? $i OFS : $i ORS | "sort -t, -nk2" }' file.txt

结果:

Rain,0264,little stone,11-09-1982
Susan,1261,Menlo park,12-13-1989
Zack,1594,columbus,02-04-1984
Mark,2218,Palo Alto,04-23-1984
Alice,2368,columbus,03/11/1988
Ted,2368,Portland,06-11-1992
Xiao,2571,Carson,07/06/1975

答案 6 :(得分:1)

只需将FS和OFS设置为您的头脑,打印您想要的字段,然后排序:

$ awk -F'[:,]' -v OFS=, '{print $2,$4,$6,$8}' file | sort -t, -k2n
Rain,0264,little stone,11-09-1982
Susan,1261,Menlo park,12-13-1989
Zack,1594,columbus,02-04-1984
Mark,2218,Palo Alto,04-23-1984
Alice,2368,columbus,03/11/1988
Ted,2368,Portland,06-11-1992
Xiao,2571,Carson,07/06/1975

答案 7 :(得分:0)

根据需要对其进行格式化后(我知道你有),你可以通过将数据汇总到sort -t, -k2来按第二列排序。

如果你还没有,我认为最简单的方法之一就是sed 's/[[:alnum:]]*://g'

所以整个命令都是

sed 's/[[:alnum:]]*://g' table.csv | sort -t, -k2

答案 8 :(得分:-1)

cat temp.txt | awk -F“,|:”'{print $ 2“,”$ 4“,”$ 6}“| sort -t,-k2n