Разбор временной метки с использованием sed и встроенной команды
Там есть файл с несколькими строками, содержащими текст и отметку даты или времени:
...
string1-20141001
string2-1414368000000
string3-1414454400000
...
Я хочу быстро преобразовать метки времени в даты, например так:
$ date -d @1414368000 +"%Y%m%d"
20141027
и я хочу сделать это динамически с sed
или похожий инструмент командной строки. Для тестирования я безуспешно использую это:
$ echo "something-1414454400000" | sed "s/-\(..........\)...$/-$(date -d @\\1 +'%Y%m%d')/"
date: invalid date '@\\1'
something-
но echo
Кажется, ING работает:
$ echo "something-1414454400000" | sed "s/-\(..........\)...$/-$(echo \\1)/"
something-1414454400
так что можно сделать?
4 ответа
Интересно, что здесь происходит. Некоторые указатели:
- Всегда используйте одинарные кавычки для регулярного выражения sed, если это возможно, при использовании BASH (и т. Д.), Особенно если используются специальные символы, такие как
$
, Вот почемуdate
выполняется (с-d @\\1
), прежде чем сед даже ввязывается. - Ваш "рабочий" пример эха на самом деле не (я верю):
echo \\1
производит\1
(и, как указано выше, будет делать это еще до того, как будет запущен sed). Это происходит с действительным синтаксисом замены sed, поэтому вы замените вашу группу на LHS, поэтому вывод выглядит примерно так. - Обратите внимание, что с помощью
-r
, вы можете использовать более простой / расширенный синтаксис регулярных выражений.
Трудно сказать, что делать, если у вас немного больше контекста, но чтобы решить текущие проблемы, попробуйте что-то вроде:
echo "something-1414454400000" | sed -re 's/-([0-9]{10,}).+/-$(date -d @\1 +"%Y%m%d")/'
который производит: $(date -d @1414454400)
(который вы можете затем направить sh
)
Или для более полного решения, вы можете изменить регулярное выражение для непосредственного создания команды оболочки и передать ее по конвейеру:
echo "something-1414454400000" | sed -re 's/(.*-)([0-9]{10,10}).+/echo \1$(date -d @\2 \"+%Y%M%d\")/' | sh
..producing something-20140028
awk -F- 'BEGIN { OFS=FS }
$2 ~ /^[0-9]{13}$/ {
"date -d@" $2/1000 " +%Y%m%d " | getline t; $2=t }1'
Просто попробуйте эту команду. Я проверил это. Он работает на ваших входах.
cat file | sed -E "s,(.*)-(.*),\1-`date -d @1414368000 +'%Y%m%d'`,g"
Вы можете сделать это в BASH
:
while read -r p; do
if [[ "$p" =~ ^(.+-)([0-9]{10}).{3}$ ]]; then
echo -n "${BASH_REMATCH[1]}"
date -d "@${BASH_REMATCH[2]}" +"%Y%m%d"
else
echo "$p"
fi
done < file
ВЫХОД:
string1-20141001
string2-20141026
string3-20141027