Gawk / awk: дата трубопроводов * иногда * не будет работать

StackOverflow https://stackoverflow.com/questions/2391272

Вопрос

Я пытаюсь преобразовать даты одного формата в другое: от EG «29 октября 2005 года» до 2005-10-29. У меня есть список из 625 дат. Я использую awk.

Конверсионные работы - большую часть времени. Hovewer, иногда преобразование не произойдет вообще, и переменная должна удерживать (преобразованную) дату остается неопределенным.

Это всегда происходит с точными и тем же рядами. Бег «Дата» явно (из раковины Bash) на даты этих странных строк работает нормально (даты правильно преобразованы). - Это не текстовое содержимое этих строк, которые имеют значение.

Почему это поведение, а как я могу исправить свой скрипт?
Она это:

awk 'BEGIN { FS = "unused" } { 
  x = "undefined";
  "date \"+%Y-%m-%d\" -d " $1 | getline x ;
  print $1 " = " x
}' uBXr0r15.txt \
 > bug-out-3.txt

Если вы хотите воспроизвести эту проблему:

  1. Загрузите этот файл: UBXR0R15.txt..
  2. Запустите скритп awk.
  3. Поиск "undefined" в Bug-Out-3.txt.
    («undefined» нашел 122 раза на моем компьютере.)

Тогда вы можете снова запустить скрипт, а (на моем компьютере) Bug-Out-3.txt остается без изменений - точно такие же даты остаются неопределенными.

(GAWK версия 3.1.6, Ubuntu 9.10.)

Добрые пожелания, магнус

Это было полезно?

Решение

Всякий раз, когда вы открываете трубу или файл для чтения или записи в awk, последний сначала проверка (Использование внутреннего хеша) У него уже есть труба или файл с тем же именем (Все еще открыт; если так, Он повторно использует существующий файловый дескриптор вместо того, чтобы открывать трубу или файл.

В вашем случае все записи, которые в конечном итоге undefined на самом деле дубликаты; Первый раз, когда они встречаются (то есть когда соответствующая команда date "..." -d "..." сначала выпущен) правильный результат читается в x. Отказ На последующих случаях одинаковой даты, getline пытается прочитать вторую, третью и т. Д. Линии из оригинала date труба, даже если труба была закрыта date, в результате чего x больше не назначен.

Из gawk Man-Page:

Примечание. При использовании трубы, совместного процесса или розетки для GetLine или от печати или распечатки внутри цикла вы должны использовать Close () для создания новых экземпляров команды или сокета. Awk не автоматически закрывает трубы, розетки или со-процессы, когда они возвращают eof.

Вы должны явно close Труба каждый раз после того, как вы прочитали x:

close("date \"+%Y-%m-%d\" -d " $1)

Кстати, это будет хорошо sort а также uniq uBXr0r15.txt перед трубопроводом в awk, или вам нужен оригинальный заказ / дублирование?

Другие советы

Хотя я люблю awk, это не нужно для этого.

tr -d '"' < uBXr0r15.txt | date +%Y-%m-%d -f -

 gawk 'BEGIN{
       m=split("January|February|March|April|May|June|July|August|September|October|November|December",d,"|")
       for(o=1;o<=m;o++){
          months[d[o]]=sprintf("%02d",o)
       }
       FS="[, ]"
    }
    {
      gsub(/["]/,"",$1)
      gsub(/["]/,"",$4)
      t=mktime($4" "months[$1]" "$2" 0 0 0")
      print strftime("%Y-%m-%d",t)
    }' uBXr0r15.txt

Делать все внутри Gawk будет быстрее, чем вызывая внешние команды.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top