Разбор временной метки с использованием 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
Другие вопросы по тегам