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