From mark at purdue.edu Thu Dec 27 11:58:07 2018 From: mark at purdue.edu (Mark Senn) Date: Thu, 27 Dec 2018 14:58:07 -0500 Subject: [Purdue-pm] a Raku Perl 6 regular expression one-liner Message-ID: <38782.1545940687@pier.ecn.purdue.edu> Here is a Raku (also known as Perl 6) one-liner to see what groups user "fred" is in in a /etc/group file perl6 -ne '/<>/ and .say' /etc/group Each line of an /etc/group file has the format groupname:password:groupid:members (user names separated by commas) DESCRIPTION OF THE RAKU ONE-LINER: WHAT DESCRIPTION SEE perl6 we're running Raku Perl 6 [1] -n don't print anything [2] e do following expression for each line [2] ' start the expression / start a regex [3] << match a word start, same as ? >> match a word end, same as ? / end a regex and if regex matches do what's after "and" .say print $_ followed by a newline, same as $_.say ' end the expression /etc/group the file to read [1] https://colabti.org/irclogger/irclogger_log/perl6?date=2018-10-25#l584 [2] https://perl6.online/2018/12/20/using-command-line-options-in-perl-6-one-liners/ [3] Regexes were formerly known as regular expressions. https://docs.perl6.org/language/regexes THE FINE PRINT <> will not match 'winifred'. The above one liner will match group names, passwords, or gids containing 'fred'. Change '/<>/' to '/.*:<>/'. The '.*:' matches everything up to and including the last colon. -mark From mark at purdue.edu Thu Dec 27 17:46:14 2018 From: mark at purdue.edu (Mark Senn) Date: Thu, 27 Dec 2018 20:46:14 -0500 Subject: [Purdue-pm] corrected "Raku Perl 6 regular expression one-liner" Message-ID: <35923.1545961574@pier.ecn.purdue.edu> Earlier I wrote: Here is a Raku (also known as Perl 6) one-liner to see what groups user "fred" is in in a /etc/group file perl6 -ne '/<>/ and .say' /etc/group Each line of an /etc/group file has the format groupname:password:groupid:members (user names separated by commas) DESCRIPTION OF THE RAKU ONE-LINER: WHAT DESCRIPTION SEE perl6 we're running Raku Perl 6 [1] -n don't print anything [2] e do following expression for each line [2] ' start the expression / start a regex [3] << match a word start, same as ? >> match a word end, same as ? / end a regex and if regex matches do what's after "and" .say print $_ followed by a newline, same as $_.say ' end the expression /etc/group the file to read [1] https://colabti.org/irclogger/irclogger_log/perl6?date=2018-10-25#l584 [2] https://perl6.online/2018/12/20/using-command-line-options-in-perl-6-one-liners/ [3] Regexes were formerly known as regular expressions. https://docs.perl6.org/language/regexes THE FINE PRINT <> will not match 'winifred'. The above one liner will match group names, passwords, or gids containing 'fred'. Change '/<>/' to '/.*:<>/'. The '.*:' matches everything up to and including the last colon. The '.*:' does not match everything up to and including the last colon! Regexes in Raku Perl 6 are extremely powerful---much more powerful than in Perl 5. From https://docs.perl6.org/language/regexes You can prevent backtracking in regexes by attaching a : modifier to the quantifier: Let's do this better. perl6 -ne '.split(":")[*-1].match(/<>/) and .say' z DESCRIPTION OF THIS RAKU ONE-LINER: WHAT DESCRIPTION perl6 We're running Raku Perl 6. -n Don't print anything. e Do following expression for each line. ' Start the expression. .split(":") Split the line into an array, breaking at colons. Split is optimized and is probably much faster than a regular expression ever could be for this. Plus, I think this is much easier to understand. [*-1] Get the whatever'th minus one element of the array. "whatever" is a very handy general concept in Perl 6. .match( Does that match a regex? (Formerly called a regular expression.) / Start the regex. << Match a word start, same as "?" if you prefer that. I like to use the same size operators for everything so nothing gets lost in the "fine print". If we just used "/fred/", "winifred" would also be matched. fred Match "fred". >> Match a word end, same as "?" if you prefer that. / End the regex ) End the "match(". and If the regex matches, do what's after the "and". .say Print $_ followed by a newline, same as "$_.say". ' End the expression. z The file to read. Using a z file of abc:def:gg abc:fred:ddd abc:ddd:fred abc:ddd:eee,fred,fff abc:ddd:eee,fff,fred abc:ddd:eee,fred2,fff abc:ddd:eee,2fred,fff abc:ddd:eee,2fred2,fff gives abc:ddd:fred abc:ddd:eee,fred,fff abc:ddd:eee,fff,fred -mark