I need to find and replace a date format in a SQL script with sed . The original lines are like this:
ep.begin_date, ep.end_date, ep.facility_code,
AND ep.begin_date <= '01-JUL-2019'
ep.begin_date, ep.end_date, ep.facility_code,
AND ep.begin_date <= '01-JUL-2019'
ep.begin_date, ep.end_date, ep.facility_code,
AND ep.begin_date <= '01-JUL-2019'
Then I want to replace '01-JUL-2019' with variable which real value is '01-OCT-2019'. After replacement, the line in file should be like this:
AND ep.begin_date <= '01-OCT-2019'. I am not good at how to use sed to identify delimiter or separator and help sed to find right part of this string and replace it with right value. Please help with your code. My testing code is ugly so that I do not post them. I would like to learn from all of you. Thanks for help.
How specific the date regex has to be? Is it OK to match 31-FEB? Any condidtions for the year, e.g. only 20xx, or 19xx as well? Does your sed handle EREs? Try
NEWDATE=01-OCT-2019
sed -r "s/[0-3][0-9]-($(locale abmon | tr 'a-z;' 'A-Z|'))-[12][09][0-9]{2}/$NEWDATE/" file
ep.begin_date, ep.end_date, ep.facility_code,
AND ep.begin_date <= '01-OCT-2019'
ep.begin_date, ep.end_date, ep.facility_code,
AND ep.begin_date <= '01-OCT-2019'
ep.begin_date, ep.end_date, ep.facility_code,
AND ep.begin_date <= '01-OCT-2019'
Thanks for your questions and advice. My Unix is Solaris 10. It seems sed do not support EREs. Please see following output. As for date regex is concerned, this format was created by some other people and has been in production for years. I could not change it at this moment. So the best expression will still be like '01-MON-20XX' or '31-MON-20XX'. These dates are government fiscal quarter begin date and end date. It is in SQL statement. I want to use shell script to automate the change to new quarter begin date and end date for data process and report generation. You are absolutely right. $NEWDATA is variable which is queried from database and put with sed to replace old date. Here is output:
/home/oracle> sed -r "s/[0-3][0-9]-($(locale abmon | tr 'a-z;' 'A-Z|'))-[12][09][0-9]{2}/"'01-OCT-2019'"/" test4.txt
sed: illegal option -- r
/home/oracle> sed -E "s/[0-3][0-9]-($(locale abmon | tr 'a-z;' 'A-Z|'))-[12][09][0-9]{2}/"'01-OCT-2019'"/" test4.txt
sed: illegal option -- E
/home/oracle> sed -e "s/[0-3][0-9]-($(locale abmon | tr 'a-z;' 'A-Z|'))-[12][09][0-9]{2}/"'01-OCT-2019'"/" test4.txt
ep.begin_date, ep.end_date, ep.facility_code,
AND ep.begin_date <= '01-JUL-2019'
ep.begin_date, ep.end_date, ep.facility_code,
AND ep.begin_date <= '01-JUL-2019'
ep.begin_date, ep.end_date, ep.facility_code,
AND ep.begin_date <= '01-JUL-2019'
Now question is: based on Solaris 10, how can sed handle the extended regular expressions? Please give me some idea. Thanks.
To write months verbatim and escape, it didn't work either. I need sed identify months because 4 quarters have 4 different begin date and 4 end date. Hard code will not work. I tried something. Please see all output below. Here, $NEWDATE=01-OCT-2019.
/home/oracle> sed "s/[0-3][0-9]-\(JUN\|JUL\|AUG\)-[12][09][0-9]\{2\}/$NEWDATE/" test4.txt
ep.begin_date, ep.end_date, ep.facility_code,
AND ep.begin_date <= '01-JUL-2019'
ep.begin_date, ep.end_date, ep.facility_code,
AND ep.begin_date <= '01-JUL-2019'
ep.begin_date, ep.end_date, ep.facility_code,
AND ep.begin_date <= '01-JUL-2019'
/home/oracle/> sed "s/[0-3][0-9]\-[a-zA-Z]{3}\-[12][09][0-9]\{2\}/$NEWDATE/" test4.txt
ep.begin_date, ep.end_date, ep.facility_code,
AND ep.begin_date <= '01-JUL-2019'
ep.begin_date, ep.end_date, ep.facility_code,
AND ep.begin_date <= '01-JUL-2019'
ep.begin_date, ep.end_date, ep.facility_code,
AND ep.begin_date <= '01-JUL-2019'
Thanks for suggestion, I tried. It output the same result. I know the Date format in our SQL script is not configured well. But I cannot make change at this time. It will cause many changes. On our Solaris 10, we have /usr/xpg4/bib/sed , can this sed work?
These two use vgersh99's proposal and without {2}
/home/oracle> sed -e "s/[0-3][0-9]-($(locale abmon | tr 'a-z;' 'A-Z|'))-[12][09][0-9][0-9]/$NEWDATE/" test4.txt
ep.begin_date, ep.end_date, ep.facility_code,
AND ep.begin_date <= '01-JUL-2019'
ep.begin_date, ep.end_date, ep.facility_code,
AND ep.begin_date <= '01-JUL-2019'
ep.begin_date, ep.end_date, ep.facility_code,
AND ep.begin_date <= '01-JUL-2019'
/home/oracle> sed "s/[0-3][0-9]\-[a-zA-Z]{3}\-[12][09][0-9][0-9]/$NEWDATE/" test4.txt
ep.begin_date, ep.end_date, ep.facility_code,
AND ep.begin_date <= '01-JUL-2019'
ep.begin_date, ep.end_date, ep.facility_code,
AND ep.begin_date <= '01-JUL-2019'
ep.begin_date, ep.end_date, ep.facility_code,
AND ep.begin_date <= '01-JUL-2019'
I am working on how to restrict to match the month. Thanks for your help.
Now the problem is that sed cannot find or match the month. If sed match the old date, then new date will replace it. I will continue to debug step by step. Thanks a lot.
Yes. I missed a / and tested again. The result is still not working. It seems that sed cannot find MON in lines. This part- s/\(JUN\|JUL\|AUG\) is not functioning. see output,
/home/oracle> /usr/xpg4/bin/sed "s/\(JUN\|JUL\|AUG\)/$NEWDATE/" test4.txt
ep.begin_date, ep.end_date, ep.facility_code,
AND ep.begin_date <= '01-JUL-2019'
ep.begin_date, ep.end_date, ep.facility_code,
AND ep.begin_date <= '01-JUL-2019'
ep.begin_date, ep.end_date, ep.facility_code,
AND ep.begin_date <= '01-JUL-2019'
Thanks. I debugged as this, this time, sed found the specific MON and replace it with whole value of $NEWDATE. But the DD and YYYY are not searched and replaced. I put DD in search, then the command doesn't work again. Here is output,
/home/oracle> /usr/xpg4/bin/sed "s/\(JUL\)/$NEWDATE/" test4.txt
ep.begin_date, ep.end_date, ep.facility_code,
AND ep.begin_date <= '01-01-OCT-2019-2019'
ep.begin_date, ep.end_date, ep.facility_code,
AND ep.begin_date <= '01-01-OCT-2019-2019'
ep.begin_date, ep.end_date, ep.facility_code,
AND ep.begin_date <= '01-01-OCT-2019-2019'
/home/oracle> /usr/xpg4/bin/sed "s/[0-3][0-9]\(JUL\)/$NEWDATE/" test4.txt
ep.begin_date, ep.end_date, ep.facility_code,
AND ep.begin_date <= '01-JUL-2019'
ep.begin_date, ep.end_date, ep.facility_code,
AND ep.begin_date <= '01-JUL-2019'
ep.begin_date, ep.end_date, ep.facility_code,
AND ep.begin_date <= '01-JUL-2019'
I have tried different ways. it didn't work. So I will take stupid way to do this work. I will pick up $OLDDATE and $NEWDATE two variables from database. Then: