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