Can you convert a date to yyyy/mm/dd using sed?

Viewed 110

I have a utility that outputs the software expiration date into a text file called expiration. The file has one line and it is below:

node_software_expiration_date Sat Jul 6 23:59:59 2025

I'd like to replace the text in the file to read:

node_software_expiration_date 20250706

I'm using sed to replace the current text. I can't edit the utility. Open to other options.

I'm running this in cron:

./export_expiration && sed -e 's/Software Expiration/node_software_expiration_date /' > expiration

6 Answers

You can use date --date=STRING to parse pretty much any free-form date string (it accepts many different syntaxes, so is pretty robust), and then +FMT to output whatever format you want. The main difficultly with your example is replacing the file in place. Something like:

read prefix date < expiration
echo $prefix $(date --date="$date" +%Y%m%d) > expiration

should do the trick in a shell script. Note that if the input date string includes a time close to midnight in some other timezone, this may end up adjusting the day by one, which might actually be what you want.

Using any awk in any shell on every Unix box:

$ awk '{printf "%s %04d%02d%02d\n", $1, $6, (index("JanFebMarAprMayJunJulAugSepOctNovDec",$3)+2)/3, $4}' file
node_software_expiration_date 20250706

Using GNU sed

$ sed -i "s/\([^ ]* \)\(.*\)/echo \1\$(date -d '\2' +'%Y%m%d')/e" input_file
$ cat input_file
node_software_expiration_date 20250706

This might work for you (GNU sed):

sed -E 's/$/\nJan01Feb02Mar03Apr04May05Jun06Jul07Aug08Sep09Oct10Nov11Dec12/
        s/ (. ..:..:.. )/ 0\1/
        s/... (...) (..) ..:..:.. (....)\n.*\1(..).*/\3\4\2/' file

Append a lookup table.

Cater for the first nine days of a month.

Pattern match, forming the result in the desired format.

$ awk '{n=$1; $1=""; printf "%s ",n; print |"date -d \"" $0 "\" +%Y%m%d"} file
node_software_expiration_date 20250706

I suggest following simple if somewhat long GNU sed solution, let file.txt content be node_software_expiration_date Sat Jul 6 23:59:59 2025 then

sed -e 's/ \([0-9]\) / 0\1 /g' -e 's/\([^ ]*\) \([^ ]*\) \([^ ]*\) \([^ ]*\) \([^ ]*\)$/\5 \2 \3/' -e 's/ Jan /01/' -e 's/ Feb /02/' -e 's/ Mar /03/' -e 's/ Apr /04/' -e 's/ May /05/' -e 's/ Jun /06/' -e 's/ Jul /07/' -e 's/ Aug /08/' -e 's/ Sep /09/' -e 's/ Oct /10/' -e 's/ Nov /11/' -e 's/ Dec /12/' file.txt

gives output

node_software_expiration_date 20250706

Explanation: firstly pad single digit (digit surrounded with spaces) using 0 to width of 2. Then extract and change order of fields to that of desired format: that is year, month, day. Finally replace callsign of month and surrounding spaces with zero-padded number.

(tested in GNU sed 4.2.2)

Related