我有一个像这样的文件
$> cat testfile.txt
abc_xyz_2a foo
dft_pqr_abc_5c bar
pqr_ijk_1a alpha
efg_5b beta
ijk_pqr_5a gamma
pqr_ijk_1b alpha
我想根据第一列的最后一个值排序行,在最后一个下划线_
之后,如1a
,2a
,5a
,5b
5c
所以这是我的预期输出。
pqr_ijk_1a alpha
pqr_ijk_1b alpha
abc_xyz_2a foo
ijk_pqr_5a gamma
efg_5b beta
dft_pqr_abc_5c bar
有人可以建议一种方法来实现预期的产出吗?
我尝试了什么
我尝试在第一列的最后一个下划线之后提取部分并进行排序,但这只会打印这些关键字,而不是整行。
$> awk '{print $1}' testfile.txt|rev|awk -F_ '{print $1}'|rev|sort
1a
2a
5a
5b
5c
我想有可能有办法以某种方式保持/记录行数并根据它输出?我在awk中使用NR
尝试了一些点击和试用失败。
编辑:在以1b
结尾的文件中添加了一行来处理另一个案例。根据它改变了预期的产出。
答案 0 :(得分:3)
只需删除所需的列,对其进行排序,然后再将其删除。
$ cat data
abc_xyz_2a foo
dft_pqr_abc_5c bar
pqr_ijk_1a alpha
efg_5b beta
ijk_pqr_5a gamma
$ awk '{print substr($1, length($1)-1, 1), substr($1, length($1)), $1, $2}' data | sort -n -k1,2 | awk '{print $3,$4}'
pqr_ijk_1a alpha
abc_xyz_2a foo
ijk_pqr_5a gamma
efg_5b beta
dft_pqr_abc_5c bar
以下是管道的每一步都会发生的事情:
$ awk '{print substr($1, length($1)-1, 1), substr($1, length($1)), $1, $2}' data
2 a abc_xyz_2a foo
5 c dft_pqr_abc_5c bar
1 a pqr_ijk_1a alpha
5 b efg_5b beta
5 a ijk_pqr_5a gamma
$ awk '{print substr($1, length($1)-1, 1), substr($1, length($1)), $1, $2}' data | sort -n -k1,2
1 a pqr_ijk_1a alpha
2 a abc_xyz_2a foo
5 a ijk_pqr_5a gamma
5 b efg_5b beta
5 c dft_pqr_abc_5c bar
答案 1 :(得分:2)
如果您有gnu-awk
,那么您可以使用PROCINFO
方式对数组进行排序:
awk 'BEGIN{PROCINFO["sorted_in"] = "@ind_num_asc"} {
n=split($1, a, "_")
data[a[n]]=$0
}
END {
for (i in data)
print data[i]
}' file
pqr_ijk_1a alpha
abc_xyz_2a foo
ijk_pqr_5a gamma
efg_5b beta
dft_pqr_abc_5c bar
否则您可以使用awk-sort-cut
管道:
awk '{n=split($1, a, "_"); print $0 "\0" a[n]}' file | sort -t '\0' -k2 | cut -d $'\0' -f1
pqr_ijk_1a alpha
abc_xyz_2a foo
ijk_pqr_5a gamma
efg_5b beta
dft_pqr_abc_5c bar
答案 2 :(得分:-1)
你可以尝试下面更简单直接的命令。
rev test.txt | sort -k2 | rev
pqr_ijk_1a alpha
abc_xyz_2a foo
ijk_pqr_5a gamma
efg_5b beta
dft_pqr_abc_5c bar