nursyza has asked for the wisdom of the Perl Monks concerning the following question:
I'm a newbie in Perl. I need some help with this coding.
MODULE C17 (N1, N2, N3, N6, N7, N22, N23);
Based on the line above, I want to program so that it will print out only the name "MODULE C17".
Here is the coding that I tried but it prints out the whole line.
my $MODULE_NAME = $_; if (defined($MODULE_NAME) && ($MODULE_NAME =~ /MODULE (.*);/)) { my $module_name = $1; print "Module name = $module_name\n"; }
|
---|
Replies are listed 'Best First'. | |||
---|---|---|---|
Re: Pattern matching
by Athanasius (Archbishop) on Nov 10, 2018 at 08:54 UTC | |||
Hello nursyza, and welcome to the Monastery! Parentheses within a regex are for capturing a match. To match a literal left parenthesis, you have to escape it:
Output:
Note: The /x modifier is used here to make the regex more readable. The regex says: match the beginning of a line (^), then capture as many characters as possible, providing that these captured characters are followed by (a) one or more spaces, then (b) an opening (left) parenthesis. Update: My use of \s+ above is sub-optimal, because it matches only the last whitespace character following the module name. Better would be:
which explicitly removes trailing whitespace from the module name. Hope that helps,
| [reply] [d/l] [select] | ||
by nursyza (Novice) on Nov 10, 2018 at 09:10 UTC | |||
Sorry i might forget to mention that the line MODULE C17 (N1, N2, N3, N6, N7, N22, N23) is actually obtained from a text file.
I tried your coding but it also prints the NAND line. | [reply] [d/l] | ||
by hippo (Bishop) on Nov 10, 2018 at 09:37 UTC | |||
Unfortunately, what you have provided now is still not a complete spec. You might want any of these things: So, your first task is to create a tight specification. After that you can devise an algorithm and only then start to consider the coding. | [reply] | ||
Re: Pattern matching
by parv (Parson) on Nov 10, 2018 at 09:02 UTC | |||
Above could not possibly "print[s] the whole line" for "MODULE " will be missing. As you are capturing any- & everything after "MODULE " with "(.*)", so you would get "C17 (N...)" string. Capture what you actually want. Surely there must be some other patterns besides one specific case? What are they? In this specific case, try ...
| [reply] [d/l] | ||
by nursyza (Novice) on Nov 10, 2018 at 09:17 UTC | |||
Thank you. And btw can you explain to me how to read the patterns you wrote? | [reply] | ||
by parv (Parson) on Nov 10, 2018 at 09:35 UTC | |||
| [reply] [d/l] | ||
by AnomalousMonk (Archbishop) on Nov 10, 2018 at 23:50 UTC | |||
... can you explain to me how to read the patterns ... Because parv's regex contains nothing that is not supported by Perl version 5.6, the YAPE::Regex::Explain module can help.
Give a man a fish: <%-{-{-{-< | [reply] [d/l] [select] | ||
by parv (Parson) on Nov 11, 2018 at 01:46 UTC | |||
by kevbot (Vicar) on Nov 11, 2018 at 00:06 UTC | |||
I see that parv already provided you with an explanation of the regex pattern for you. I wanted to let you know that you can use the YAPE::Regex::Explain module to provide an explanation of any regular expression pattern. Once you have the package installed you can do something like this at the command line to get the explanation for your pattern Read more... (4 kB)
You may also want to look at perlre to get more familiar with regular expressions. UPDATE: As parv, soonix, and AnomalousMonk pointed out (in the replies to this node), the above usage of YAPE::Regex::Explain is not correct. Passing the regex as a double-quoted string caused problems.
The following code gives the correct output Here is the output
| [reply] [d/l] [select] | ||
by parv (Parson) on Nov 11, 2018 at 01:53 UTC | |||
by soonix (Canon) on Nov 11, 2018 at 21:18 UTC | |||
| |||
by nursyza (Novice) on Nov 10, 2018 at 09:14 UTC | |||
It works now. Thank you! | [reply] | ||
Re: Pattern matching
by haj (Vicar) on Nov 10, 2018 at 09:03 UTC | |||
Welcome to the monastery! In Perl, the parentheses define what you are capturing. With (.*) you are capturing everything up to the semicolon, therefore you get everything except the leading MODULE into $1. Depending on how your input varies, you could use one of the following:
Note that in the second regex I had to escape the opening parenthesis to tell Perl that this is the character ( and not the start of a new capturing group. | [reply] [d/l] | ||
Re: Pattern matching
by Laurent_R (Canon) on Nov 10, 2018 at 10:59 UTC | |||
You've received good answers already, but I would add that the syntax could be simplified. Assuming that your target string is in the $_ default variable because you're reading the file in a while loop (for example a while (<$IN>) { # ... construct, assuming $IN is your file descriptor), then you don't need to test for "definedness," because the while loop already does that check. You also don't need the extra $MODULE_NAME variable; using directly the $_ variable makes the regex syntax simpler (if you don't specify any target string, a regex will by default match against $_). So putting this together, you could have something like this: Or, using the /x modifier already described by other monks:
| [reply] [d/l] [select] |