FYI,

Thanks William for the consult.

The use case is a particular log that is kept in a lot of appliances I manage & 
they can get out of hand.  Thankfully the log utility that I use to fetch them 
has a 'WHERE begintime > ...' option.  After the script that uses this snippet 
passes through, I get real DateTimes from each record, & stash the latest for 
each node.  For the next run, I read the DateTimes and ask only for records 
that are newer.  That particular script monitors ((6 x 8) + (2 x 14)) of these 
spastic logs.  Raku made short work of it (and thank you Promises...).  Concise 
reports every morning now, delivered in seconds.

My solution for the question I posed in the mailing list:

#!/usr/bin/env raku

my $data = q:to/END/;
    3_1    2025-08-30T03:06:44-04:00    info        Advanced Intrusion 
Detection Environment (AIDE) detected potential changes to software on this 
system. The changes are listed in /var/log/aide/aide.log and also at the end of 
this alert message.
                                                    Summary : :
                                                    Total number of entries : 
54096
                                                    Added entries : 1
                                                    Removed entries : 0
                                                    Changed entries : 0
    1_1    2025-08-14T07:18:41-04:00    critical    After initial accelerated 
space reclamation, file system / is 80% full, which is equal to or above the 
80% threshold. Accelerated space reclamation will continue.
                                                    This alert will be cleared 
when file system / becomes less than 75% full.
                                                    Top three directories 
ordered by total space usage are as follows:
                                                    /opt        : 2.69G
                                                    /root        : 2.15G
                                                    /usr        : 1.76G
    1_2    2025-08-14T17:36:40-04:00    clear       File system / is 58% full, 
which is below the 75% threshold. Normal space reclamation will resume.
END

my grammar EXADATALOG-grammar {
    token TOP                   { <log-record>+                                 
                            }
    token log-record            { <log-record-start> || <log-record-continue>   
                            }
    token log-record-start      { ^^ <log-record-herald> \s+ <log-text>         
                            }
    token log-record-herald     { \s* <name> \s+ <datetime> \s+ <status>        
                            }
    token log-record-continue   { ^^ <!before <log-record-herald>> <log-text>   
                            }
    token name                  { \d+ '_' \d+                                   
                            }
    token datetime              { \d\d\d\d '-' \d\d '-' \d\d 'T' \d\d ':' \d\d 
':' \d\d '-' \d\d ':' \d\d   }
    token status                { \w+                                           
                            }
    token log-text              { .+? \n                                        
                            }
}

class EXADATALOG-record {
    has Str         $.name      is required;
    has DateTime    $.datetime  is required;
    has Str         $.status    is required;
    has Str         @.message;
}

my @EXADATALOG-records;

class EXADATALOG-actions {
    method log-record-herald ($/) {
        @EXADATALOG-records.push:   EXADATALOG-record.new(
            :name(~$/<name>),
            :datetime(DateTime.new(~$/<datetime>)),
            :status(~$/<status>),
        );
    }

    method log-text ($/) {
        @EXADATALOG-records[* - 1].message.push: ~$/.chomp;
    }
}

EXADATALOG-grammar.parse($data, :actions(EXADATALOG-actions));

for @EXADATALOG-records -> $record {
    printf "%-6s%-28s%-10s\n", $record.name, $record.datetime, $record.status;
    printf "\t%s\n", $record.message.join("\n");
}

=finish

Mark

________________________________
From: William Michels <[email protected]>
Sent: Monday, October 27, 2025 11:32 AM
To: [email protected] <[email protected]>
Subject: Re: Grammar: "match anything that is not this thing"

Hi Mark,

You could try a Boolean condition-check:

https://stackoverflow.com/questions/64909029/is-it-possible-to-do-boolean-assertions-with-raku-regex<https://urldefense.proofpoint.com/v2/url?u=https-3A__stackoverflow.com_questions_64909029_is-2Dit-2Dpossible-2Dto-2Ddo-2Dboolean-2Dassertions-2Dwith-2Draku-2Dregex&d=DwMFaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=thT0VsM9yJlPPLROt23gXb6x82v5JicoCnxKT8v5YUo&m=ghZ4xkUVGPjDg8LDBOViDXYfnvxS-3xU7BNUSwYO6kvU5E87OgSJXY5KseI_nIT-&s=RYDHWVLmPaaMdNi46IpYmYqEC5jLTYLaa5ZQMk2LazI&e=>

https://docs.raku.org/language/regexes#Regex_Boolean_condition_check<https://urldefense.proofpoint.com/v2/url?u=https-3A__docs.raku.org_language_regexes-23Regex-5FBoolean-5Fcondition-5Fcheck&d=DwMFaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=thT0VsM9yJlPPLROt23gXb6x82v5JicoCnxKT8v5YUo&m=ghZ4xkUVGPjDg8LDBOViDXYfnvxS-3xU7BNUSwYO6kvU5E87OgSJXY5KseI_nIT-&s=RUUsdBOYb3_IgL5bwJt_Fr7a--4S6ZksnHFoL0K5v58&e=>

Darren Duncan had a similar question here on the mailing list, back in July 
2023 (second like below is my reply):

https://www.nntp.perl.org/group/perl.perl6.users/2023/07/msg11016.html<https://urldefense.proofpoint.com/v2/url?u=https-3A__www.nntp.perl.org_group_perl.perl6.users_2023_07_msg11016.html&d=DwMFaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=thT0VsM9yJlPPLROt23gXb6x82v5JicoCnxKT8v5YUo&m=ghZ4xkUVGPjDg8LDBOViDXYfnvxS-3xU7BNUSwYO6kvU5E87OgSJXY5KseI_nIT-&s=YInPBYSJ0Xnu-HOFWejCXe1RIPqqIzyMmdlE-44rNh4&e=>

https://www.nntp.perl.org/group/perl.perl6.users/2023/07/msg11018.html<https://urldefense.proofpoint.com/v2/url?u=https-3A__www.nntp.perl.org_group_perl.perl6.users_2023_07_msg11018.html&d=DwMFaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=thT0VsM9yJlPPLROt23gXb6x82v5JicoCnxKT8v5YUo&m=ghZ4xkUVGPjDg8LDBOViDXYfnvxS-3xU7BNUSwYO6kvU5E87OgSJXY5KseI_nIT-&s=vcD_QMfhpF2rUeq_VpfiDxLVxvlslJOE5KZKide02Zo&e=>

HTH, Bill.


On Oct 26, 2025, at 12:35, Mark Devine <[email protected]> wrote:

The logic of the idea seems to be sound, but I see here that 
<not-log-record-herald> matches “” (blank).  I was hoping that 
<not-log-record-herald> would consider the string a match and pack it in the 
Match object.  I’d use an action to accumulate if necessary.  But since it 
discards the string, I think I might be out of luck entirely.  Thoughts?

TOP
> |  log-record
>
|  |  log-record-herald
>
|  |  |  name-field
>
|  |  |  * MATCH "3_1"
>
|  |  |  datetime-field
>
|  |  |  * MATCH "2025-08-30T03:06:44-04:00"
>
|  |  |  status-field
>
|  |  |  * MATCH "info"
>
|  |  * MATCH "    3_1    2025-08-30T03:06:44-04:00    info"
>
|  |  message
>
|  |  |  not-log-record-herald
>
|  |  |  |  log-record-herald
>
|  |  |  |  * FAIL
>
|  |  |  * MATCH ""

Thanks,

Mark
From: Mark Devine <[email protected]>
Sent: Saturday, October 25, 2025 1:16 PM
To: [email protected]
Subject: Grammar: "match anything that is not this thing"

RE Gurus,

I have a “match anything that is not this thing” pattern that I haven’t worked 
out yet.

Colorized below is the (log) data to parse, sometimes multi-line, sometimes 
single line, in a repeated pattern.  Here’s my test script:

#!/usr/bin/env raku

use Data::Dump::Tree;
use Grammar::Debugger;

my $data = q:to/END/;
    3_1    2025-08-30T03:06:44-04:00    info        Advanced Intrusion 
Detection Environment (AIDE) detected potential changes to software on this 
system. The changes are listed in /var/log/aide/aide.log and also at the end of 
this alert message.
                                                    Summary : :
                                                    Total number of entries : 
54096
                                                    Added entries : 1
                                                    Removed entries : 0
                                                    Changed entries : 0
    1_1    2025-08-14T07:18:41-04:00    critical    After initial accelerated 
space reclamation, file system / is 80% full, which is equal to or above the 
80% threshold. Accelerated space reclamation will continue.
                                                    This alert will be cleared 
when file system / becomes less than 75% full.
                                                    Top three directories 
ordered by total space usage are as follows:
                                                    /opt        : 2.69G
                                                    /root        : 2.15G
                                                    /usr        : 1.76G
    1_2    2025-08-14T17:36:40-04:00    clear       File system / is 58% full, 
which is below the 75% threshold. Normal space reclamation will resume.
END

my grammar EXADATALOG-grammar {
    token TOP                   { <log-record>+                                 
                            }
    token log-record            { <log-record-herald> \s+ <message>             
                            }
    token log-record-herald     { ^ \s+ <name-field> \s+ <datetime-field> \s+ 
<status-field>                }
    token name-field            { \d+ '_' \d+                                   
                            }
    token datetime-field        { \d\d\d\d '-' \d\d '-' \d\d 'T' \d\d ':' \d\d 
':' \d\d '-' \d\d ':' \d\d   }
    token status-field          { \w+                                           
                            }
    token not-log-record-herald { <!log-record-herald>                          
                            }
    token message               { <not-log-record-herald>+                      
                            }
}

ddt EXADATALOG-grammar.parse($data);

=finish

My strategy is to characterize the start of each record with  
<log-record-herald> as the anchor for the logic.  Match a <log-record-herald> 
and match a potentially multi-line <message>, with <message> being anything 
that IS NOT a<log-record-herald>.

Is this a viable approach?  Anyone know what I’m missing here?

Thanks,

Mark

Reply via email to