user3347022
user3347022

Reputation: 259

Trying to change date string in a file to different format with sed

So i am trying to change all dates in a text file from

1-1-1111(Month,Day,Year)

to

January 1, 1111(Month,Day,Year)
sed 's/[0-9]\{1\}-[0-9]\{1\}-[0-9]\{4\}/date -d"+%B +%d, +%Y"/g'

I'm not sure how to format from "date" on. If I add other single quotes it won't function correctly. It is not functioning correctly as is but I know i want to use

date -d"+%B +%d, +%Y"

on the second half of

sed's///g'

Upvotes: 1

Views: 1574

Answers (3)

choroba
choroba

Reputation: 241828

You can generate the sed script in bash to avoid calls to external tools:

#!/bin/bash

idx=12
for month in Dec Nov Oct Sep Aug Jul Jun May Apr Mar Feb Jan ; do
    echo "s/$idx-\([0-9]\{1,2\}\)-\([0-9]\{4\}\)/$month \1, \2/g"
    (( idx-- ))
done

Note that I use the months in reverse order to prevent 12 to be translated to 1Feb.

Saved as script.sh, it generates the following sed script:

s/12-\([0-9]\{1,2\}\)-\([0-9]\{4\}\)/Dec \1, \2/g
s/11-\([0-9]\{1,2\}\)-\([0-9]\{4\}\)/Nov \1, \2/g
s/10-\([0-9]\{1,2\}\)-\([0-9]\{4\}\)/Oct \1, \2/g
s/9-\([0-9]\{1,2\}\)-\([0-9]\{4\}\)/Sep \1, \2/g
s/8-\([0-9]\{1,2\}\)-\([0-9]\{4\}\)/Aug \1, \2/g
s/7-\([0-9]\{1,2\}\)-\([0-9]\{4\}\)/Jul \1, \2/g
s/6-\([0-9]\{1,2\}\)-\([0-9]\{4\}\)/Jun \1, \2/g
s/5-\([0-9]\{1,2\}\)-\([0-9]\{4\}\)/May \1, \2/g
s/4-\([0-9]\{1,2\}\)-\([0-9]\{4\}\)/Apr \1, \2/g
s/3-\([0-9]\{1,2\}\)-\([0-9]\{4\}\)/Mar \1, \2/g
s/2-\([0-9]\{1,2\}\)-\([0-9]\{4\}\)/Feb \1, \2/g
s/1-\([0-9]\{1,2\}\)-\([0-9]\{4\}\)/Jan \1, \2/g

Then, run

script.sh | sed -f- file

Upvotes: 1

choroba
choroba

Reputation: 241828

Perl to the rescue (using Time::Piece):

perl -MTime::Piece -pe 'BEGIN { @months = ( undef, Time::Piece::mon_list() ) }
                        s/([0-9]{1,2})-([0-9]{1,2})-([0-9]{4})/$months[$1] $2, $3/g' < input > output

Upvotes: 0

mcoolive
mcoolive

Reputation: 4205

In your example, you use simple quote to protect the sed expression, that's why you CANNOT use other simple quote inside (there is no escape in this case).

If your sed is GNU sed. you can use 'e' to pass matched group to external command/tools within sed command as explained here.

But it means you call an external command for each match. So this solution can be slow if your text contains a lot of dates.

If you have only one date by line, I suggest the following script :

sed -r 's#([0-9]{1,2})-([0-9]{1,2})-([0-9]{4})#date -d"\1/\2/\3" +"%B %d, %Y"#e'

Upvotes: 2

Related Questions