I am trying to replace a word in a string with the current timestamp and for this I am using sed. However, sed updates the string with a single time timestamp value for all the 1000 records. How can I update the records so that I get actual timestamp.
cat toreplacefile.txt
TIMESTAMP_line1
TIMESTAMP_line2
TIMESTAMP_line3
TIMESTAMP_line4
TIMESTAMP_line5
sed 's/TIMESTAMP/$(date "%Y-%m-%dT%H:%M:%S.%3N")/g' toreplacefile.txt
2022-11-14T10:11:43.654_line1
2022-11-14T10:11:43.654_line2
2022-11-14T10:11:43.654_line3
2022-11-14T10:11:43.654_line4
2022-11-14T10:11:43.654_line5
However, what I am expecting is a time change atleast in milliseconds.
2022-11-14T10:11:43.654_line1
2022-11-14T10:11:43.656_line2
2022-11-14T10:11:43.657_line3
2022-11-14T10:11:43.660_line4
2022-11-14T10:11:43.661_line5
CodePudding user response:
You would need to slow down the execution of the code yourself to see a difference in the timestamp, e.g. using a 'while loop' to go through the file line-by-line:
while read -r line
do
echo "$line" | sed "s/TIMESTAMP/$(date "%Y-%m-%dT%H:%M:%S.%3N")/"
done < toreplacefile.txt
# result
2022-11-14T21:59:41.875_line1
2022-11-14T21:59:41.887_line2
2022-11-14T21:59:41.901_line3
2022-11-14T21:59:41.913_line4
2022-11-14T21:59:41.924_line5
Edit
One potential option without using sed
:
while read -r line
do
echo "${line//TIMESTAMP/$(date "%Y-%m-%dT%H:%M:%S.%3N")}"
done < toreplacefile.txt
# result
2022-11-14T22:00:01.126_line1
2022-11-14T22:00:01.132_line2
2022-11-14T22:00:01.138_line3
2022-11-14T22:00:01.149_line4
2022-11-14T22:00:01.155_line5
CodePudding user response:
GNU sed
has a very convenient extension that allows to execute the result of a substitution with the shell. And as one new shell is spawned for each line of your input this is slow enough to see time differences. With your example:
$ sed -E 'h;s/.*/date %FT%T.%3N/e;G;s/(.*)\n(.*)TIMESTAMP/\2\1/' ~/tmp/toreplacefile.txt
2022-11-14T13:03:04.995_line1
2022-11-14T13:03:05.005_line2
2022-11-14T13:03:05.016_line3
2022-11-14T13:03:05.025_line4
2022-11-14T13:03:05.033_line5
That is, for a <PREFIX>TIMESTAMP<SUFFIX>
line:
- Store the pattern space (the current line) in the hold space.
- Replace the pattern space by
date %FT%T.%3N
, execute the result with the shell and replace the pattern space by the result. - Append a new line followed by the content of the hold space (the original line).
At this point the pattern space contains something like (with a newline between the date and the original line):
2022-11-14T13:03:04.995
<PREFIX>TIMESTAMP<SUFFIX>
- Use the substitute command one last time to get
<PREFIX>2022-11-14T13:03:04.995<SUFFIX>
without the newline.
Note: you could try the much simpler:
sed 's/TIMESTAMP/date %FT%T.%3N/e'
But this works only because date %FT%T.%3N_line1
outputs something like 2022-11-14T13:03:04.995_line1
. With more complex line prefix and/or suffix it would probably not. You would likely get errors or even worse (imagine what would happen with TIMESTAMP; rm -rf *
). So, prefer the safe version.