1

I have a file with the following:

$ cat file.txt
on that date April 02, 2020 end of line
March 5, 2021 helloooo world
J 14, 2022
error 3, bye

I want to change the date format from "month day, year" to "day month year". The month always starts with a capital letter, the day is one or two digits and the year is 4 digits.

Desired output:

on that date 02 April 2020 end of line
5 March 2021 helloooo world
14 J 2022
error 3, bye

i tried the below, can get the day and year but cannot get the month

sed -r 's/([0-9]*[0-9]), ([0-9]{4})//g'

How can I do this with sed on a Linux system?

4
  • 14 J 2022 is not a valid date; how you validate which is date which is not then? like 02 Ja 02 is a valid date and how? – αғsнιη Nov 26 '20 at 17:56
  • as i mentioned here, The month always starts with a capital letter, the day is one or two digits and the year is 4 digits and always in this format month day, year – peter louis Nov 26 '20 at 18:02
  • 1
    @peterlouis so would Fooobarasdasdkjansdjiabskdjabsd 00 9999 be a valid date? – terdon Nov 26 '20 at 18:05
  • OK, so will not validate a string like Xyz 99, 2020 is not a valid date and you will just change it to 99 Xyz 2020? – αғsнιη Nov 26 '20 at 18:05
3

Here's one way assuming your data are as you show and you don't have anything like Foo 12, 0000 which should not be considered as a date):

$ sed -E 's/([A-Z][a-z]+) ([0-9]{1,2}), ([0-9]{4})\b/\2 \1 \3/g' file
on that date 02 April 2020 end of line
5 March 2021 helloooo world
J 14, 2022
error 3, bye

We look for a capital letter followed by one or more lower case letters ([A-Z][a-z]+), then a space and one or two numbers ([0-9]{1,2}), then a comma and a space and exactly 4 numbers followed by a word-boundary (\b: a word to non-word transition; this will match a space, or the end of the line or anything else that isn't a word character). The parentheses capture the relevant groups into \1, \2 and \3 which we then use for the replacement.

Note that this does not work for J 14, 2022 since that is not a valid date. For example, is M 14 2020 the 14th of March or of May? If you really want to match things like that as well, you can try:

$ sed -E 's/([A-Z][a-z]*) ([0-9]{1,2}), ([0-9]{4})\b/\2 \1 \3/g' file
on that date 02 April 2020 end of line
5 March 2021 helloooo world
14 J 2022
error 3, bye

Finally, you could also make it a bit more specific by only looking for capital letters that can be found as the first letter of a month:

sed -E 's/([JFMASOND][a-z]*) ([0-9]{1,2}), ([0-9]{4})\b/\2 \1 \3/g' file
2
  • appreciated! thanks a lot. worked – peter louis Nov 26 '20 at 18:11
  • FWIW you could make it even more specific by changing [a-z]* to [a-z]{2,8}. – Ed Morton Nov 27 '20 at 17:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.