我正在学习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排序。
我会用什么命令来做这件事?
答案 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吗?如果不是:
Vim
删除:%s/[a-z]*://gi
sort -t , -k 2 file
如果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