How to change date format in sed?
Say I want to convert a date in timestamp to another format through the date
command. In console I would say date -d@<timestamp>
but I happen to want to do this to many fields in a text file.
Using the e
to execute in sed
(sed (GNU sed) 4.2.2
, actually) I am saying:
$ echo 1449158360 | sed -r 's#.*([0-9]{10}).*#date -d@\1 "+%Y";#e'
2015
It works, nice!
Now I created a dummy file myfile
:
my timestamp is 1449158360 but also I wonder what date was 1359199960.
Which I would like to have replaced to the same but having the relative year of the timestamps:
my timestamp is 2015 but also I wonder what date was 2013.
However, if I try to run the same command as above it fails:
$ sed -r 's#([0-9]{10})#date -d@"\1" "+%Y";#e' myfile
sh: my: command not found
sh: but: command not found
Because sed
interprets the first words as something to execute.
Obviously it works if I just fetch these data and nothing else:
$ sed -r 's#.*([0-9]{10}).*#date -d@"\1" "+%Y";#ge' myfile
2015
So I wonder: what should I do to call date
against captured groups in sed
and replace text with it, considering it is surrounded by other text that have to remain untouched?
e
switch in sed
substitute applies sh -c
to unmatched text as well as evident from this command:
echo 'a 1449158360' | sed -r 's#([0-9]{10})#date -d@\1 "+%Y";#e'
sh: a: command not found
So even though we are matching only 1449158360
but sh -c
is being run on a 1449158360
.
Due to absence of non-greedy and lookaheads regex in sed
this workaround regex might appear crazy but this is how you can run it for multiple matching input from file as in your question:
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
Basically we are matching <before>10-digits<after>
in this regex.
Output:
my timestamp is 2015 but also I wonder what date was 2013.
To clarify the regex used I have created this demo.
By no means this is a generic solution to e
mode issue, treat it as a regex based workaround.