Unix 使用awk和sort按ID字段对表进行排序
我正在学习Unix,我想对这个表进行排序:Unix 使用awk和sort按ID字段对表进行排序,unix,sorting,awk,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
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
我想过滤掉键值对(key:value)中的键,然后使用awk和sort按ID排序
我将使用哪些命令来执行此操作?我发现的最简单的方法是使用
awk
重新格式化输出,并附加一个排序将使用的新列,然后再次使用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存在输出问题。为了简单起见,我只是重新分配了第一个变量(您希望隐藏的列)并打印整行。必须有awk吗?如果没有:
使用Vim
删除带有:%s/[a-z]*:///gi
使用sort进行排序:sort-t,-k2文件
如果AWK是必须的,那么我会想,在不丢失密钥的情况下进行排序-但是@Aif给出的答案也很好
编辑:由于@Aif的正则表达式和@Ghoti的评论,改进了。现在,用于替换的Vim命令使用regex和键大小写以及文本“matters not”,正如尤达大师所说。我花了一段时间才弄清楚,直到我最终发现输入数据中的“birth”拼写错误
您可以全力以赴,将数据解析为实际数据:
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
这将产生相同的结果,但代码更少。如果你需要用你的输入数据做更多有趣的事情,那么当然,awk是一个不错的选择
哦,我的sed
来自FreeBSD,所以它使用-E
选项来获取ERE。如果您使用的是Linux或其他GNU-sed提供商,您可能可以在根据需要格式化后(我知道您已经格式化了)用-r
替换-E
,您可以通过管道将数据传输到排序-t,-k2
按第二列排序
如果您实际上还没有,我认为最简单的方法之一是sed的//[:alnum:]*://g'
所以整个命令都是
sed 's/[[:alnum:]]*://g' table.csv | sort -t, -k2
这里有一种使用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
就这么简单:
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
使用grep查找值,粘贴以重新组合行,当然还有排序:
grep -oP '(?<=:).*?(,|$)' filename | paste -d "" - - - - | sort -n -t, -k2
grep-oP'(?只需将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
cat temp.txt | awk-F“,|:“{print$2”,“$4”,“$6}”sort-t,-k2n(1)您可以使keyname的大小写与vi命令无关:将ic
设置为IgnoreCase。以及(2)这对于一次性操作很好,但无法轻松地自动化vim命令。最后,(3)您的“使用awk排序”链接实际上是用于GAWK,而不是awk。如果OP没有提到他的平台,那么一个好的答案将是非教派的,并且在任何地方都有效,而不仅仅是在你最喜欢的平台上。Ad Vim命令:(1)它区分大小写,因此我在@Aif的答案中标记了它(2)非常好的正则表达式(这里的第一个)很可能被用于区分大小写,这是一个没有实际意义的观点。广告“我的链接”,它涵盖了Gnu Awk和Awk,向下滚动它所指向的页面,亲自查看:“标准Awk”部分。然而,我发现GAWK的asorti()
值得注意的是,因为Awk答案已经存在,所以它有什么问题吗?请解释一下这比@Aif的答案好吗?好吧,aifs的答案有3个管道和4个不同的命令,代码太多了。但是这里只有一个管道和两个命令。您还没有选择答案,所以答案是正确的ovided显然不适合你。你能描述一下没有涵盖的内容吗?无用的使用cat,awk…temp.txt
也同样有效,并节省了一个(可能会失速)管道。
grep -oP '(?<=:).*?(,|$)' filename | paste -d "" - - - - | sort -n -t, -k2
$ 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