Home > other >  How do I add characters in dates to make them look normal without affecting the rest of the line?
How do I add characters in dates to make them look normal without affecting the rest of the line?

Time:02-10

I have a file with tons of lines using a semicolon (;) as a delimiter. I have about 5 fields and need to change the format of only the first 2 fields without affecting the remainder of each line

20211119000751;20211119000759;IDNumber;Code;THings;SomeStuff

I want the end result to look like

2021-11-19 00:07:51;2021-11-19 00:07:59;IDNumber;Code;THings;SomeStuff

I have tried the solution How Do I add Multiple characters using SED? (My first Poorly Made question) and change date format from DD/MM/YYYY to YYYY-MM-DD with sed doesn't make sense to me.

sed -e 's/\(....\)\(..\)\(..\)\(..\)\(..\)\(..\);\(.*\)/\1-\2-\3 \4:\5:\6;\7/' \
    -e 's/\(.*\);\(....\)\(..\)\(..\)\(..\)\(..\)\(..\)/\1;\2-\3-\4 \5:\6:\7/' \
    < input > output

This solution makes sense, but affects the rest of the line.

CodePudding user response:

Using awk:

$ awk -v FS=";" '

function process_date(date)
{
        # 20211119000751 -> 2021-11-19 00:07:51
        new_date = substr(date, 1, 4) \
        "-" \
        substr(date, 5, 2) \
        "-" \
        substr(date, 7, 2) \
        " " \
        substr(date, 9, 2) \
        ":" substr(date, 11, 2) \
        ":" substr(date, 13, 2)

        return new_date
}
BEGIN { OFS=FS }
{ $1 = process_date($1); $2 = process_date($2); print $0}' input

CodePudding user response:

Crappy but working solution (each line add a character at a given position /./ select any char the n number at the end is the number of repetition of the selected pattern, so /4 repeat /./ 4 times & is the selected motif, plus a character, sor for example : `s/./&-/4' take any first 4 character, and replace them by & ("Re-add" the pattern itself) plus a character. Everything of that piped into another sed.

I usually use python for date formatting, plus the easy csv parsing, if it's a possible solution for you.

sed 's/./&-/4' < input.csv | \
sed 's/./&-/7' | \
sed 's/./&\ /10' | \
sed 's/./&:/13' | \
sed 's/./&:/16' | \
sed 's/./&-/24' | \
sed 's/./&-/27' | \
sed 's/./&\ /30' | \
sed 's/./&\:/33' | \
sed 's/./&\:/36' >> output.csv

CodePudding user response:

Use capture-groups with fixed number of digits.

sed -E 's/([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})/\1-\2-\3 \4:\5:\6/g' input > output

CodePudding user response:

Since only bash is tagged, here's a solution using bash's string indexing:

while IFS=\; read -r x y z
do printf '%s;%s;%s\n' \
  "${x::4}-${x:4:2}-${x:6:2} ${x:8:2}:${x:10:2}:${x:12:2}" \
  "${y::4}-${y:4:2}-${y:6:2} ${y:8:2}:${y:10:2}:${y:12:2}" \
  "$z"
done
  •  Tags:  
  • bash
  • Related