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}'
Использование 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
Вы можете сделать это с помощью этой команды грубой силы 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
.
(Если вы хотите, чтобы в выводе были начальные пробелы, как показывает ваш вопрос,
добавьте их в эту команду.) Примечания:
Использование 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