парсинг файла и манипуляции с датой в bash с большим файлом - PullRequest
1 голос
/ 29 марта 2019

Я ищу лучший способ манипулирования форматом даты в то, что я хочу.Мне удается это сделать, но мне приходится обрабатывать файлы несколько раз, потому что я не могу заставить date сделать это за один проход.

Формат, который у меня есть:
Wed Jan 30 08:00:00 2019 : misc data

Формат, который я хочу:
30/01/2019 08:00:00 : misc data

Однако я могу получить date только для обработки информации о дате, если она имеет формат:
30-Jan-2019 08:00:00 : misc data

(примечание: misc data - длинная строка, содержащая много громоздких символов)

Для достижения того, что я хочу, я использую:

awk '{("date --date="$3"-"$2"-"$5"\\ "$4" +%F") | getline $1;$2="";$3="";$4;$5=""} 1' oldfile | tr -s ' ' > newfile

То, что это делает, создаетформат, который я могу использовать, разбирает его на поля $ 1, очищает поля 2, 3 и 5, распечатывает его (сохраняя время в поле 4 и разное данные) и удаляет лишние пробелы, оставленные пустыми полями, и сохраняет егов новый файл.Затем я должен манипулировать форматом, включая разделители (потому что date не нравится / при использовании именованного месяца) в новом формате, и весь процесс становится слишком сложным.

Я тогдазапустите еще один awk, поменяйте местами поля и разделители.

Я уверен, что это можно упростить, но теперь это начинает меня смущать.

Я осознаю, что должен использовать вывод format из date, но поскольку косые черты связаны, как только я включаю одинарные или двойные кавычки или пытаюсь их избежать, я нахожу, что всене удается задействовать несколько элементов формата.

Что еще хуже, все это работает, когда я работаю с ограниченным набором данных (обычно выборка ограничена head или tail, но исходный файл составляет около 20 000записей длинных, и он завершается с ошибкой FNR=1043 при слишком большом количестве открытых файлов. Это только один открытый файл и один сохраненный файл. Я думаю, что это в результате использования getline. Есть ли способ сделать это без его использования??

Ответы [ 2 ]

3 голосов
/ 29 марта 2019

Вам не нужно вызывать date, чтобы просто перемешать текст:

$ echo 'Wed Jan 30 08:00:00 2019 : misc data' |
awk '{
    mthNr = (index("JanFebMarAprMayJunJulAugSepOctNovDec",$2)+2)/3
    date = sprintf("%02d/%02d/%04d %s", $3, mthNr, $5, $4)
    sub(/^([^ ]+ +){5}/,"")
    print date, $0
}'
30/01/2019 08:00:00 : misc data

Ошибка too many open files, которую вы получили, кстати, заключается в том, что вы не закрываете канал после каждого вызова getline,См. http://awk.freeshell.org/AllAboutGetline, когда и как надежно использовать getline.

0 голосов
/ 29 марта 2019

Другое awk

$ echo 'Wed Jan 30 08:00:00 2019 : misc data' | awk -F: -v OFS=: ' { t=$NF;NF--; 
    cmd="date -d\047" $0 "\047 \047+%d/%m/%Y %T\047"; if ( (cmd | getline line) > 0 ) 
    close(cmd); print line,t}'
30/01/2019 08:00:00: misc data
$
...