Home > front end >  sed substitues with a single timestamp value for all the records
sed substitues with a single timestamp value for all the records

Time:11-14

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.

  • Related