what I have is an already processed ICS file which contains these three lines for each event:
SUMMARY:"Description"
DTSTART;VALUE=DATE:20230612
DTEND;VALUE=DATE:20230201
The dates can be in two forms:
DATE:20230201
DATE:20220908T153000
I need a bash script that sutracts one day from DTEND date if it's in the short form.
DTEND;VALUE=DATE:20230201
would be DTEND;VALUE=DATE:20230131
after the script is through.
Dates in long format should be unchanged.
Tried with awk:
#!/bin/bash
# Input file
input_file="input_file.txt"
output_file="output_file.txt"
# Process the file with awk
awk '
/^DTEND;/ {
# Extract the date part after "DTEND;"
split($0, arr, ";")
date = arr[length(arr)]
# Check if the date format is YYYYMMDD (8 digits)
if (match(date, /^[0-9]{8}$/)) {
# Parse year, month, day
year = substr(date, 1, 4)
month = substr(date, 5, 2)
day = substr(date, 7, 2)
# Calculate the previous day using date command
prev_date = strftime("%Y%m%d", mktime(year " " month " " day " 00 00 00") - 86400)
# Replace the original date with the previous day date
sub(date, prev_date, $0)
}
}
{ print }
' "$input_file" > "$output_file"
echo "Processing complete. Output saved to $output_file"
But after running the script nothing happend to the dates in short format. Guess i miss something.
Any help would be great ;-) Ps.: No need to use awk, could also be sed or any other command that is available in bash.
Additional Info:
I also tried with another approach: Leave the last 4 digits of dates as 4 digit integer numbers and subtract 1 from that number. Therefor I need a case selection for month boundaries:
case 0201 then 0131
and so forth.
I can omit the january first problem (which would also alter the year since 20220101 - 1 -> 20211231) since there can not be a DTEND on the first of january.
But could not get this second approach to work neither.
You split your array on ;
(semicolon). So you get 2 elements and the second is something like VALUE=DATE:20230612
. Split on :
(colon), instead. And you could use a more accurate regex to select the lines of interest:
awk -F: -v OFS=: '/^DTEND;VALUE=DATE:[0-9]{8}\r?$/ {
y=substr($2,1,4); m=substr($2,5,2); d=substr($2,7,2); r=substr($2,9)
$2 = strftime("%Y%m%d", mktime(y " " m " " d " 0 0 0") - 86400) r}
1' "$input_file" > "$output_file"
Note the \r?
at the end of the regexp and the use of the r=substr($2,9)
variable, such that this works with UNIX file format (lines terminated with \n
) and DOS file format (lines terminated with \r\n
).
Note: just like your own version this requires GNU awk
for the strftime
function.