1

I want to do something in a Shell script without adding a dependency, so have to rely on awk/sed.

Namely, I want to replace the content of a line in a file, without affecting the rest of the file. But I only know the start of the line. For example, the line might be

CURRENT_DATE 2020-03-02

or it can be

CURRENT_DATE 2019-04-01

Or any other date -t he only part I know is that it starts with CURRENT_DATE. And I want to put the actual current date there instead. And the line is in the middle of the file and no other lines should be affected.

So how do I do this? While sed is typical for replacements, I am kinda lost because of the required wildcard.

1
  • 1
    awk '/CURRENT_DATE/{$2="18-07-2020"}1' file Commented Jul 17, 2020 at 21:17

4 Answers 4

4
$ cat file
foo
CURRENT_DATE 2020-03-02
bar

$ sed 's/^\(CURRENT_DATE\).*/\1 '"$(date +'%F')"'/' file
foo
CURRENT_DATE 2020-07-17
bar

$ awk -v d="$(date +'%F')" '$1=="CURRENT_DATE"{$2=d} 1' file
foo
CURRENT_DATE 2020-07-17
bar
1
echo 'CURRENT_DATE 2020-03-02' |
    awk '/^CURRENT_DATE/ { print "CURRENT_DATE " strftime("%Y-%m-%d"); }'

CURRENT_DATE 2020-07-17
2
  • 2
    Note that strftime is a GNU extension (now also supported by mawk and busybox awk but generally not elsewhere). Commented Jul 18, 2020 at 7:52
  • 1
    You can use %F instead of %Y-%m-%d (applies to all answers).
    – Ed Morton
    Commented Jul 18, 2020 at 17:57
0

Making sure you match the whole line so ...

  • ^ the start of the line
  • CURRENT DATE the invariant text
  • [0-9]{4} something that should be a year, could change this to 20[0-2][0-9] to refine the year if you wanted
  • (-[0-9]{2}){2} two groups that look like a month and a day with a leading -
  • $ the end of the line

And so

cat file 

foo
CURRENT_DATE 2020-03-02
bar
banana CURRENT_DATE 2020-03-02
CURRENT_DATE 2020-03-02 banana

with

awk '/^CURRENT_DATE [0-9]{4}(-[0-9]{2}){2}$/{$2=strftime("%Y-%m-%d")}1' file

or

sed -E "s/^(CURRENT_DATE )[0-9]{4}(-[0-9]{2}){2}$/\1"$(date +'%F')"/" file

both yield

foo
CURRENT_DATE 2020-07-18
bar
banana CURRENT_DATE 2020-03-02
CURRENT_DATE 2020-03-02 banana

And we could go deeper to validate the date if we really wanted to, either with regex or arithmetically

awk '$1=="CURRENT_DATE"&&NF==2{
    split($2,d,"-");
    if (d[1]*d[2]*d[3]>0&&d[1]<2021&&d[2]<13&&d[3]<32)$2=strftime("%Y-%m-%d")}1' file

Just for fun date validation (incl leap years)

awk '$1=="CURRENT_DATE"&&NF==2{
    if (split($2,d,"-")==3 && d[1]*d[2]*d[3]>0){
      leapyear=((d[1]%4==0&&d[1]%100!=0)||(d[1]%400==0))?1:0;     
      month=d[2]+int(d[2]/8);
      monthdays=(30+month%2-((month==2)?2-leapyear:0)))*(month<14);
      now=strftime("%Y-%m-%d");
      if ($2<=now&&d[3]<=monthdays)$2=now
      }}1' file
0

Below command Matches the regular expression and replaces

cat file

CURRENT_DATE 2020-03-02
CURRENT_DATE 2019-04-01
praveen
ajay
abhi
san
2019-04-01

command

sed "/^CURRENT_DATE/s/CURRENT_DATE.*[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}/CURRENT_DATE $(date +%Y-%m-%d)/g"  file

output

CURRENT_DATE 2020-07-18
CURRENT_DATE 2020-07-18
praveen
ajay
abhi
san
2019-04-01

python

#!/usr/bin/python
import re
import datetime
from datetime import date
cu=date.today()
k=re.compile(r'^CURRENT_DATE [0-9]{4}-[0-9]{2}-[0-9]{2}')
m=open('file','r')
for g in m:
    if re.search(k,g):
        ou=re.sub(k,"CURRENT_DATE {0}".format(cu),g)
        print ou.strip()
    else:
        print g.strip()

output

CURRENT_DATE 2020-07-18
CURRENT_DATE 2020-07-18
praveen
ajay
abhi
san
2019-04-01

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .