-1

I have an ics file with a lot of events. Want to improve it a bit by adding a LOCATION: tag based on the description part. Any ideas on how to do this? Do I need to do a grep/sed/awk combination or write a python script to edit it? Add a new line with a tag first or do it simultaneously with a moving pattern? Do I need to split the file into parts or just work on one? I thought about every n-line rule, but adding a blank line breaks that rule. The bad example below:

BEGIN:VEVENT
DESCRIPTION:Student plan\n\n Date: 2023.03.10 friday\n\n Time from: 17:30\n\n Time to: 19:00\n\n Hours: 2h00m\n\n Subject: Maths \n\n Room: 124A \n\n Teacher: John Smith \n\n 
DTEND:20230310T190000
DTSTAMP:20230227T140621Z
DTSTART:20230310T173000
SEQUENCE:0
SUMMARY:Math
UID:dcea6c77-3c51-4101-a62a-e4949e937fa9
END:VEVENT

As you can see there is a Room: XXX \n\n pattern. It could be moved or copied - doesn't matter.

Exepted:
BEGIN:VEVENT
DESCRIPTION:Student plan\n\n Date: 2023.03.10 friday\n\n Time from: 17:30\n\n Time to: 19:00\n\n Hours: 2h00m\n\n Subject: Maths \n\n Room: 124A \n\n Teacher: John Smith \n\n 
LOCATION:Room: 124A
DTEND:20230310T190000
DTSTAMP:20230227T140621Z
DTSTART:20230310T173000
SEQUENCE:0
SUMMARY:Math
UID:dcea6c77-3c51-4101-a62a-e4949e937fa9
END:VEVENT
AnTiVERT
  • 1
  • 1
  • 1
    (bash with sed) or awk can do this. Python can do it too, perl, C, ... What language are you confortable with? Use that. Extract the room location from the description and add the new LOCATION line after the DESCRIPTION line. Get started, show what you have done, research. See [ask]. – Nic3500 Feb 28 '23 at 16:50
  • `printf '%b\n' 'g/DESCRIPTION/t.\\\ns/.*\(Room: [^ ]*\).*/LOCATION:\\1/' ,p Q | ed -s ics.txt` – Jetchisel Mar 01 '23 at 09:27

2 Answers2

0

Her you go:

#!/bin/sh

BASE=`basename "$0" ".sh" `

input="${BASE}.sampleIN"
cat >"${input}" <<"EnDoFiNpUt"
BEGIN:VEVENT
DESCRIPTION:Student plan\n\n Date: 2023.03.10 friday\n\n Time from: 17:30\n\n Time to: 19:00\n\n Hours: 2h00m\n\n Subject: Maths \n\n Room: 124A \n\n Teacher: John Smith \n\n
DTEND:20230310T190000
DTSTAMP:20230227T140621Z
DTSTART:20230310T173000
SEQUENCE:0
SUMMARY:Math
UID:dcea6c77-3c51-4101-a62a-e4949e937fa9
END:VEVENT
EnDoFiNpUt

awk -v matchStr="Room:" 'BEGIN{
    pshift=length(matchStr) ;
}{
    if( $0 ~ /^DESCRIPTION/ ){
        pos=index( $0, matchStr ) ;
        rem=substr( $0, pos+pshift ) ;
        split( rem, vals ) ;
        print $0 ;
        printf("LOCATION:%s %s\n", matchStr, vals[1] ) ;
    }else{
        print $0 ;
    } ;
}' "${input}"
Eric Marceau
  • 1,601
  • 1
  • 8
  • 11
0

Alternative solution using awk:

If line starts with 'DES', then use awk match function to capture text matching Room: and at least one alphanumeric character [[:alnum:]]+. Now use that capture group to redefine the current line to include a newline and the targeted text. Now rely on the awk shorthand for default no condition {print} which is '1'. 1 is the condition, which always evaluates to true. The action is omitted, so the default {print} is performed.

awk '/^DES/ {match($0,/(Room: [[:alnum:]]+)/); $0=$0"\nLOCATION:"substr($0, RSTART, RLENGTH)}1' src.ics

Output:

BEGIN:VEVENT
DESCRIPTION:Student plan\n\n Date: 2023.03.10 friday\n\n Time from: 17:30\n\n Time to: 19:00\n\n Hours: 2h00m\n\n Subject: Maths \n\n Room: 124A \n\n Teacher: John Smith \n\n 
LOCATION:Room: 124A
DTEND:20230310T190000
DTSTAMP:20230227T140621Z
DTSTART:20230310T173000
SEQUENCE:0
SUMMARY:Math
UID:dcea6c77-3c51-4101-a62a-e4949e937fa9
END:VEVENT

src.ics contents:

BEGIN:VEVENT
DESCRIPTION:Student plan\n\n Date: 2023.03.10 friday\n\n Time from: 17:30\n\n Time to: 19:00\n\n Hours: 2h00m\n\n Subject: Maths \n\n Room: 124A \n\n Teacher: John Smith \n\n 
DTEND:20230310T190000
DTSTAMP:20230227T140621Z
DTSTART:20230310T173000
SEQUENCE:0
SUMMARY:Math
UID:dcea6c77-3c51-4101-a62a-e4949e937fa9
END:VEVENT
j_b
  • 1,975
  • 3
  • 8
  • 14
  • Nice! Elegant and compact! Just one question: What is the function of the "1" before the closing single quote for the awk statement? – Eric Marceau Mar 09 '23 at 01:50
  • For awk the 1 as used in the answer is the default print action for the current row. The awk command redefined the current row to the desired output so the 1 just prints it along with all other rows. – j_b Mar 09 '23 at 15:04
  • Wouldn't that be implicit/default? or does it need to be explicitly coded? Or is that your practice to make obvious your choice of output stream? – Eric Marceau Mar 09 '23 at 16:59
  • No, there would be no output from the command if the trailing `1` was not included. It is shorthand. The answers [here](https://stackoverflow.com/questions/20262869/why-does-1-in-awk-print-the-current-line) provide a good overview. – j_b Mar 09 '23 at 17:48