таращите глаза / awk: передача по каналу даты к getline *иногда* не будет работать

Я пытаюсь преобразовать даты от одного формата до другого: От, например, "29 октября 2005" до 29.10.2005. У меня есть список 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. Поиск "неопределенного" в bug-out-3.txt.
    ("неопределенные" найденные 122 раза, на моем компьютере.)

Затем Вы могли запустить скрипт снова, и (на моем компьютере), bug-out-3.txt остается неизменным - точно, те же даты оставляют неопределенными.

(Версия 3.1.6 простофили, Ubuntu 9.10.)

С наилучшими пожеланиями, Magnus

6
задан KajMagnus 6 March 2010 в 03:46
поделиться

3 ответа

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

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

Из справочной страницы gawk :

ПРИМЕЧАНИЕ. При использовании конвейера, совместного процесса или сокета для получения строки или из print или printf внутри цикла, { {1}} вы должны использовать close () для создания новых экземпляров команды или сокета. AWK не закрывает автоматически каналы, сокеты или совместные процессы , когда они возвращают EOF.

Вы должны явно закрывать канал каждый раз после чтения x :

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

Между прочим, можно ли сортировать и uniq uBXr0r15.txt перед подключением к awk , или вам нужен исходный порядок / дублирование?

9
ответ дан 8 December 2019 в 16:01
поделиться

Хотя я люблю awk, в этом нет необходимости.

tr -d '"'

3
ответ дан 8 December 2019 в 16:01
поделиться
 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 будет быстрее, чем вызов внешних команд.

3
ответ дан 8 December 2019 в 16:01
поделиться
Другие вопросы по тегам:

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