Как изменить формат даты в sed?

Скажем, я хочу преобразовать дату в метку времени в другой формат через date команда. В консоли я бы сказал date -d@<timestamp> но я хочу сделать это для многих полей в текстовом файле.

С использованием e выполнить в sed (sed (GNU sed) 4.2.2собственно) я говорю:

$ echo 1449158360 | sed -r 's#.*([0-9]{10}).*#date -d@\1 "+%Y";#e'
2015

Это работает, приятно!

Теперь я создал фиктивный файл myfile:

my timestamp is 1449158360 but also I wonder what date was 1359199960.

Который я хотел бы заменить на тот же, но с относительным годом временных меток:

my timestamp is 2015 but also I wonder what date was 2013.

Однако, если я попытаюсь выполнить ту же команду, что и выше, она не будет выполнена:

$ sed -r 's#([0-9]{10})#date -d@"\1" "+%Y";#e' myfile
sh: my: command not found
sh: but: command not found

Так как sed интерпретирует первые слова как нечто для исполнения.

Очевидно, это работает, если я просто получаю эти данные и ничего больше:

$ sed -r 's#.*([0-9]{10}).*#date -d@"\1" "+%Y";#ge' myfile
2015

Поэтому мне интересно: что мне делать, чтобы позвонить date против захваченных групп в sed и заменить текст на него, считая, что он окружен другим текстом, который должен остаться нетронутым?

2 ответа

Решение

e включить sed применяется замена sh -c для непревзойденного текста, а также видно из этой команды:

echo 'a 1449158360' | sed -r 's#([0-9]{10})#date -d@\1 "+%Y";#e'
sh: a: command not found 

Так что, хотя мы сопоставляем только 1449158360 но sh -c работает на a 1449158360,

Из-за отсутствия регулярных выражений sed это временное выражение может показаться сумасшедшим, но вы можете запустить его для нескольких подходящих входных данных из файла, как в вашем вопросе:

sed -r 's#(([^0-9][0-9]{0,9})*)(\b[0-9]{10}\b)(([0-9]{0,9}[^0-9])*)#printf "%s%s%s" "\1" $(date -d@\3 "+%Y") "\4";#ge' file

В основном мы совпадаем <before>10-digits<after> в этом регулярном выражении

Выход:

my timestamp is 2015 but also I wonder what date was 2013.

Для пояснения используемого регулярного выражения я создал эту демонстрацию.

Ни в коем случае это не общее решение e проблема режима, рассматривайте это как обходное решение на основе регулярных выражений.

Как вы сказали, с флагом e sed получает все предложение как то, чтобы выполнить.

Поворот может быть что-то в этом роде.

+ Изменить myfile чтобы:

echo "my timestamp is 1449158360 but also I wonder what date was 1359199960."

затем:

sed -r 's#([0-9]{10})#\`date -d@\1 "+%Y"\`#ge' myfile

Надеюсь, это поможет

Другие вопросы по тегам