Сортировать файл на основе поля 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

Может кто-нибудь помочь

3 ответа

С помощью 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  

Если предположить, 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-

Хороший вопрос

Основная проблема в вашем вопросе

Основная проблема в вашем вопросе заключается в том, что вы на самом деле хотите отсортировать по двум полям (дата, время), из которых необходимо перевернуть (прочитать в обратном направлении) перед сортировкой, поскольку дата имеет формат dd/mm/yyyy,

Если мы сделаем это (многословно для ясности), скрипт ниже сделает это. Это:

  • сначала возвращает дату, объединяет ее с полем времени, создает кортеж и индекс строки.
  • сортирует список кортежей по дате / времени и печатает исходные строки по вновь упорядоченным индексам отсортированного списка.

Сценарий

#!/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]]
Другие вопросы по тегам