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

Может кто-то помогать

4
задан 19 August 2015 в 12:56

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  
2
ответ дан 1 December 2019 в 09:48

Принятие 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 численно вынуть данные, отсортированные согласно первому полю

  • Наконец мы удалили время эпохи для получения нашего окончательного результата.

Пример (Взятый от @A.B.):

$ 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-
2
ответ дан 1 December 2019 в 09:48

Деликатный вопрос.

Основной вопрос в Вашем вопросе

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

Если мы делаем это (подробным способом по причинам ясности), сценарий ниже делает это. Это:

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

Сценарий

#!/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]]
0
ответ дан 1 December 2019 в 09:48

Другие вопросы по тегам:

Похожие вопросы: