根据文件内容的字段 3 对文件进行排序

根据文件内容的字段 3 对文件进行排序

这是文件的内容

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

使用sortawk

假设你的日期格式如下

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_positionlength

    返回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

  • partsline如果用空格分隔,数组将包含不同的部分

  • 然后,我们提取相关日期时间字段并将其设置为正确的格式,然后使用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]]

相关内容