这是文件的内容
090100010000481074 1 08/03/2015 09:35:15.934 LA150803000AJSX00000 LA150803000AJSX CRBP Buy ELF 100 1980000 119 3 2 1890000 119 100 2040000 119 100 1980000 119 1000 #Q 2
我想按字段 3($3) 排序
08/03/2015 09:35:15.934
有人可以帮忙吗
答案1
使用sort
和awk
假设你的日期格式如下
08/03/2015
–> 日、月、年
使用以下命令。
- 它是一命令(请注意
\
行末的) - 替换
your_input_file
为您的文件名。
命令
awk '{for (i=1;i<=NF;i++) {if (i==3) {printf "%s/%s/%s\t",substr($3,7,4),substr($3,4,2),substr($3,1,2)} else {printf "%s\t",$i}} printf "\n"}' your_input_file |\
sort -k3 -k4 |\
awk '{for (i=1;i<=NF;i++) {if (i==3) {printf "%s/%s/%s\t",substr($3,9,2),substr($3,6,2),substr($3,1,4)} else {printf "%s\t",$i}} printf "\n"}'
分解
第一个
awk
命令将日期从day/month/year
08/03/2015
到
year/month/day
2015/03/08
该
sort
命令对新结构进行排序第二次撤销对第一次撤销的
awk
修改awk
如果你的日期格式不正确day/month/year
,你必须更改部分
substr($3,7,4),substr($3,4,2),substr($3,1,2)
和
substr($3,9,2),substr($3,6,2),substr($3,1,4)
解释
substr(field,start_position,length)
field
不要改变,这是第三列
start_position
,length
返回
start_position
长度为length
例子
输入文件foo
cat foo
090100010000481074 1 08/03/2015 09:35:17.934 LA150803000AJSX00000 LA150803000AJSX CRBP Buy ELF 100 1980000 119 3 2 1890000 119 100 2040000 119 100 1980000 119 1000 #Q 2
090100010000481074 1 07/03/2015 09:35:15.934 LA150803000AJSX00000 LA150803000AJSX CRBP Buy ELF 100 1980000 119 3 2 1890000 119 100 2040000 119 100 1980000 119 1000 #Q 2
090100010000481074 1 07/03/2015 09:35:17.934 LA150803000AJSX00000 LA150803000AJSX CRBP Buy ELF 100 1980000 119 3 2 1890000 119 100 2040000 119 100 1980000 119 1000 #Q 2
090100010000481074 1 08/03/2015 09:35:15.934 LA150803000AJSX00000 LA150803000AJSX CRBP Buy ELF 100 1980000 119 3 2 1890000 119 100 2040000 119 100 1980000 119 1000 #Q 2
090100010000481074 1 08/03/2016 09:35:17.934 LA150803000AJSX00000 LA150803000AJSX CRBP Buy ELF 100 1980000 119 3 2 1890000 119 100 2040000 119 100 1980000 119 1000 #Q 2
090100010000481074 1 03/07/2016 09:35:15.934 LA150803000AJSX00000 LA150803000AJSX CRBP Buy ELF 100 1980000 119 3 2 1890000 119 100 2040000 119 100 1980000 119 1000 #Q 2
090100010000481074 1 07/03/2016 09:35:17.934 LA150803000AJSX00000 LA150803000AJSX CRBP Buy ELF 100 1980000 119 3 2 1890000 119 100 2040000 119 100 1980000 119 1000 #Q 2
090100010000481074 1 08/03/2015 09:35:15.934 LA150803000AJSX00000 LA150803000AJSX CRBP Buy ELF 100 1980000 119 3 2 1890000 119 100 2040000 119 100 1980000 119 1000 #Q 2
输出
awk '{for (i=1;i<=NF;i++) {if (i==3) {printf "%s/%s/%s\t",substr($3,7,4),substr($3,4,2),substr($3,1,2)} else {printf "%s\t",$i}} printf "\n"}' foo | sort -k3 -k4 | awk '{for (i=1;i<=NF;i++) {if (i==3) {printf "%s/%s/%s\t",substr($3,9,2),substr($3,6,2),substr($3,1,4)} else {printf "%s\t",$i}} printf "\n"}'
090100010000481074 1 07/03/2015 09:35:15.934 LA150803000AJSX00000 LA150803000AJSX CRBP Buy ELF 100 1980000 119 3 2 1890000 119 100 2040000 119 100 1980000 119 1000 #Q 2
090100010000481074 1 07/03/2015 09:35:17.934 LA150803000AJSX00000 LA150803000AJSX CRBP Buy ELF 100 1980000 119 3 2 1890000 119 100 2040000 119 100 1980000 119 1000 #Q 2
090100010000481074 1 08/03/2015 09:35:15.934 LA150803000AJSX00000 LA150803000AJSX CRBP Buy ELF 100 1980000 119 3 2 1890000 119 100 2040000 119 100 1980000 119 1000 #Q 2
090100010000481074 1 08/03/2015 09:35:15.934 LA150803000AJSX00000 LA150803000AJSX CRBP Buy ELF 100 1980000 119 3 2 1890000 119 100 2040000 119 100 1980000 119 1000 #Q 2
090100010000481074 1 08/03/2015 09:35:17.934 LA150803000AJSX00000 LA150803000AJSX CRBP Buy ELF 100 1980000 119 3 2 1890000 119 100 2040000 119 100 1980000 119 1000 #Q 2
090100010000481074 1 07/03/2016 09:35:17.934 LA150803000AJSX00000 LA150803000AJSX CRBP Buy ELF 100 1980000 119 3 2 1890000 119 100 2040000 119 100 1980000 119 1000 #Q 2
090100010000481074 1 08/03/2016 09:35:17.934 LA150803000AJSX00000 LA150803000AJSX CRBP Buy ELF 100 1980000 119 3 2 1890000 119 100 2040000 119 100 1980000 119 1000 #Q 2
090100010000481074 1 03/07/2016 09:35:15.934 LA150803000AJSX00000 LA150803000AJSX CRBP Buy ELF 100 1980000 119 3 2 1890000 119 100 2040000 119 100 1980000 119 1000 #Q
答案2
假设08/03/2015
意味着8th March, 2015
,你可以使用这个bash
一行代码:
while IFS= read -r line; do parts=( $(echo "$line") ); printf '%s %s\n' "$(date --date="$(sed -r 's_([^/]+/)([^/]+/)_\2\1_' <<<"${parts[2]} ${parts[3]}")" '+%s')" "$line"; done <file.txt | sort -k1,1n | cut -d' ' -f2-
展开形式:
while IFS= read -r line; do
parts=( $(echo "$line") )
printf '%s %s\n' "$(date --date="$(sed -r 's_([^/]+/)([^/]+/)_\2\1_' <<<"${parts[2]} ${parts[3]}")" '+%s')" "$line"
done <file.txt | sort -k1,1n | cut -d' ' -f2-
我们正在读取输入文件的每一行并将其作为变量
line
parts
line
如果用空格分隔,数组将包含不同的部分然后,我们提取相关日期时间字段并将其设置为正确的格式,然后使用
sed
在循环中,我们将首先输出纪元时间,然后再输出原始
line
时间现在,由于我们首先有了纪元,我们可以使用
sort
数字来获取根据第一个字段排序的数据最后,我们删除了纪元时间来获得最终的输出。
示例(取自@AB):
$ cat file.txt
090100010000481074 1 08/03/2015 09:35:17.934 LA150803000AJSX00000 LA150803000AJSX CRBP Buy ELF 100 1980000 119 3 2 1890000 119 100 2040000 119 100 1980000 119 1000 #Q 2
090100010000481074 1 07/03/2015 09:35:15.934 LA150803000AJSX00000 LA150803000AJSX CRBP Buy ELF 100 1980000 119 3 2 1890000 119 100 2040000 119 100 1980000 119 1000 #Q 2
090100010000481074 1 07/03/2015 09:35:17.934 LA150803000AJSX00000 LA150803000AJSX CRBP Buy ELF 100 1980000 119 3 2 1890000 119 100 2040000 119 100 1980000 119 1000 #Q 2
090100010000481074 1 08/03/2015 09:35:15.934 LA150803000AJSX00000 LA150803000AJSX CRBP Buy ELF 100 1980000 119 3 2 1890000 119 100 2040000 119 100 1980000 119 1000 #Q 2
090100010000481074 1 08/03/2016 09:35:17.934 LA150803000AJSX00000 LA150803000AJSX CRBP Buy ELF 100 1980000 119 3 2 1890000 119 100 2040000 119 100 1980000 119 1000 #Q 2
090100010000481074 1 03/07/2016 09:35:15.934 LA150803000AJSX00000 LA150803000AJSX CRBP Buy ELF 100 1980000 119 3 2 1890000 119 100 2040000 119 100 1980000 119 1000 #Q 2
090100010000481074 1 07/03/2016 09:35:17.934 LA150803000AJSX00000 LA150803000AJSX CRBP Buy ELF 100 1980000 119 3 2 1890000 119 100 2040000 119 100 1980000 119 1000 #Q 2
090100010000481074 1 08/03/2015 09:35:15.934 LA150803000AJSX00000 LA150803000AJSX CRBP Buy ELF 100 1980000 119 3 2 1890000 119 100 2040000 119 100 1980000 119 1000 #Q 2
$ while IFS= read -r line; do parts=( $(echo "$line") ); printf '%s %s\n' "$(date --date="$(sed -r 's_([^/]+/)([^/]+/)_\2\1_' <<<"${parts[2]} ${parts[3]}")" '+%s')" "$line"; done <file.txt | sort -k1,1n | cut -d' ' -f2-
090100010000481074 1 07/03/2015 09:35:15.934 LA150803000AJSX00000 LA150803000AJSX CRBP Buy ELF 100 1980000 119 3 2 1890000 119 100 2040000 119 100 1980000 119 1000 #Q 2
090100010000481074 1 07/03/2015 09:35:17.934 LA150803000AJSX00000 LA150803000AJSX CRBP Buy ELF 100 1980000 119 3 2 1890000 119 100 2040000 119 100 1980000 119 1000 #Q 2
090100010000481074 1 08/03/2015 09:35:15.934 LA150803000AJSX00000 LA150803000AJSX CRBP Buy ELF 100 1980000 119 3 2 1890000 119 100 2040000 119 100 1980000 119 1000 #Q 2
090100010000481074 1 08/03/2015 09:35:15.934 LA150803000AJSX00000 LA150803000AJSX CRBP Buy ELF 100 1980000 119 3 2 1890000 119 100 2040000 119 100 1980000 119 1000 #Q 2
090100010000481074 1 08/03/2015 09:35:17.934 LA150803000AJSX00000 LA150803000AJSX CRBP Buy ELF 100 1980000 119 3 2 1890000 119 100 2040000 119 100 1980000 119 1000 #Q 2
090100010000481074 1 07/03/2016 09:35:17.934 LA150803000AJSX00000 LA150803000AJSX CRBP Buy ELF 100 1980000 119 3 2 1890000 119 100 2040000 119 100 1980000 119 1000 #Q 2
090100010000481074 1 08/03/2016 09:35:17.934 LA150803000AJSX00000 LA150803000AJSX CRBP Buy ELF 100 1980000 119 3 2 1890000 119 100 2040000 119 100 1980000 119 1000 #Q 2
090100010000481074 1 03/07/2016 09:35:15.934 LA150803000AJSX00000 LA150803000AJSX CRBP Buy ELF 100 1980000 119 3 2 1890000 119 100 2040000 119 100 1980000 119 1000 #Q 2
另一方面,如果08/03/2015
意味着3rd August, 2015
您可以使用(无需sed
获取能够理解的正确格式date
):
while IFS= read -r line; do parts=( $(echo "$line") ); printf '%s %s\n' "$(date --date="${parts[2]} ${parts[3]}" '+%s')" "$line"; done <file.txt | sort -k1,1n | cut -d' ' -f2-
展开形式:
while IFS= read -r line; do
parts=( $(echo "$line") )
printf '%s %s\n' "$(date --date="${parts[2]} ${parts[3]}" '+%s')" "$line" done <file.txt | sort -k1,1n | cut -d' ' -f2-
答案3
好问题。
你的问题中的主要问题
你的问题中的主要问题是你实际上想要按二字段(日期、时间),其中一个需要在排序之前还原(向后读取),因为日期的格式是dd/mm/yyyy
。
如果我们这样做(为了清晰起见,以冗长的方式),下面的脚本就会这样做。它:
- 首先恢复日期,将其与时间字段相结合,创建一个元组 icw 行索引。
- 按日期/时间对元组列表进行排序,并根据排序列表的新排序索引打印出原始行。
剧本
#!/usr/bin/env python3
import sys
f = open(sys.argv[1]).readlines()
rawlist = []
for i, l in enumerate(f):
# split the line, read the date backwards for correct sorting, since it is dd/mm/yyyy now
# add the time
l = l.split(); cr = (i, l[2].split("/")[::-1]+l[3].split(":"))
rawlist.append(cr)
# sort by date, time
rawlist.sort(key=lambda x: x[1])
# print the lines by found (sorted) indexes
for i in [d[0] for d in rawlist]:
print(f[i], end = "")
如何使用
- 将脚本复制到一个空文件中,另存为
sort_byfield.py
使用文件作为参数来运行它:
python3 /path/to/sort_byfield.py <file>
例子
列表(为了清晰起见省略了一些字段):
090100010000481074 1 08/03/2014 09:35:17.932
090100010000481074 1 07/03/2015 08:22:15.934
090100010000481074 1 07/03/2015 09:55:15.933
090100010000481074 1 08/03/2013 09:01:15.934
090100010000481074 1 08/03/2013 08:35:15.934
然后输出:
090100010000481074 1 08/03/2013 08:35:15.934
090100010000481074 1 08/03/2013 09:01:15.934
090100010000481074 1 08/03/2014 09:35:17.932
090100010000481074 1 07/03/2015 08:22:15.934
090100010000481074 1 07/03/2015 09:55:15.933
简短版本
如果我们不太在意可读性,下面的版本是同一脚本的较短版本:
#!/usr/bin/env python3
import sys
f = open(sys.argv[1]).readlines()
rawlist = [(i, l.split()[2].split("/")[::-1]+l.split()[3].split(":")) for i, l in enumerate(f)]
rawlist.sort(key=lambda x: x[1])
[print(f[i], end = "") for i in [d[0] for d in rawlist]]