Изменение формата даты в файле [дубликат]

sed -n 's/.* MATCH: \([^ ]*\).*/\1/p'

Будет печатать последовательность непробельных символов, следующих за крайним правым вхождением «MATCH:» в каждая совпадающая строка.

-n сообщает sed не печатать пространство шаблонов по умолчанию. А флаг p в команде s указывает sed напечатать пространство шаблонов (то есть результат подстановки), если подстановка успешна.

Итак:

sed -n 's/pattern/replacement/p'

- это обычная идиома для вывода результатов успешных замен.

Обратите внимание, что вышесказанное предполагает, что введенный текст является допустимым. Поскольку . * соответствует любой последовательности из символов , он не будет соответствовать последовательностям байтов, которые не образуют допустимые символы. Обычно это происходит в языковых стандартах UTF-8 при обработке текста в другой кодировке. В таком случае вы можете добавить к этой строке префикс LC_ALL = C . Это заставляет sed обрабатывать каждый байт как символ, поэтому недопустимая последовательность байтов отсутствует. Здесь это сработает, поскольку все символы, которые мы сопоставляем, взяты из переносимого набора символов.

Стандартный awk не имеет ничего эквивалентного, поскольку он не поддерживает группы захвата ( \ (... \) , захваченный в \ 1 ) в своей функции sub () .

Здесь вам нужно прибегнуть к функции match () :

awk 'match($0, / MATCH: [^ ]*/) {
       print substr($0, RSTART+8, RLENGTH-8)}'

Или использовать такие уловки, как:

awk -F ' MATCH: ' 'NF>1 {sub(/ .*/, "", $2); print $2}'

(имейте в виду, что они будут учитывать крайнее левое вхождение «МАТЧ:» ).

GNU awk имеет функцию gensub () , которая имеет функциональность, аналогичную команде s в sed , но с ошибкой в ​​конструкции. в нем не говорится, была ли произведена замена. Здесь вы можете сделать:

 gawk '(replacement = gensub(/.* MATCH: ([^ ]*).*/, "\\1", 1)) != $0 {
   print replacement}'
1
20.09.2016, 22:41
3 ответа

Использование strptime / strftime из модуля perl Time :: Piece :

perl -MTime::Piece -pe '
  s/\[(.*?)\]/Time::Piece->strptime($1, "%a %b %d %H:%M:%S %Y")->strftime("%Y-%m-%d %H:%M:%S!ER_DEV")/e
' Sample.txt
2016-09-10 06:31:41!ER_DEV!Node2!Node1!Node3
2016-09-11 23:31:41!ER_DEV!Node2!Node1!Node3
1
27.01.2020, 23:19

Вы можете сделать это с помощью этой команды грубой силы sed :

sed 's/^.... //
     s/^Jan /01/; s/^Feb /02/; s/^Mar /03/; s/^Apr /04/; s/^May /05/; s/^Jun /06/
     s/^Jul /07/; s/^Aug /08/; s/^Sep /09/; s/^Oct /10/; s/^Nov /11/; s/^Dec /12/
     s/^\(..\) /\10/; s/^\(..\)\(..\)\( ........\) \(....\)./\4-\1-\2\3/'
  • s / ^ .... // удаляет [ и (трехбуквенное сокращение дня) дня недели.
  • s / ^ Jan / 01 / и т. Д. Заменяет (трехбуквенное сокращение названия) месяца (и следующий пробел) {{1} } с соответствующим числовым значением (номером месяца).
  • s / ^ \ (.. \) / \ 10 / проверяет значение даты (дня месяца) , которое является одной цифрой (т. Е. Число <10 с ведущий пробел) и заменяет его ведущим нулем. Например,
      [Сб, 3 сентября 09 3 0903
  • s / ^ \ (.. \) \ (. . \) \ (........ \) \ (.... \) ./ \ 4- \ 1- \ 2 \ 3 / преобразует оставшуюся дату / время строка от mmddHH: MM: SSYYYY ] до YYYY-mm-ddHH: MM: SS . (Если вы хотите, чтобы в выводе были начальные пробелы, как показывает ваш вопрос, добавьте их в эту команду.)

Примечания:

  • Это не обрабатывает ошибки. Если ввод не такой, как вы говорите, вывод будет зашифрован.
  • Это жестко кодирует названия месяцев на английском языке, и не адаптируется к языку.
1
27.01.2020, 23:19

Использование awk с помощью из date :

awk -F '[[\\]]' '{cmd="date -d \""$2"\" \"+%F %T\""; cmd | getline out; print out $3}'
  • -F '[[\\]]' устанавливает разделитель полей как [ или ] , поэтому дата будет в поле 2, а остальные - в поле 3

  • Переменная cmd содержит команду date для преобразования второго поля в желаемую форму, getline запускает внешнюю команду date , и вывод сохраняется в переменной out

  • Наконец, печатается содержимое переменной out и третье поле

Пример:

% cat file.txt
[Sat Sep 10 06:31:41 2016]!Node2!Node1!Node3
[Sun Sep 11 23:31:41 2016]!Node2!Node1!Node3

% awk -F '[[\\]]' '{cmd="date -d \""$2"\" \"+%F %T\""; cmd | getline out; print out $3}' file.txt
2016-09-10 06:31:41!Node2!Node1!Node3
2016-09-11 23:31:41!Node2!Node1!Node3
2
27.01.2020, 23:19

Теги

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