How to use Perl regular expression and save match to a new variable

Written by - 0 comments

Published on - Listed in Perl Coding


While working on a Perl script, I came across a problem when I wanted to save a part of a string into a new variable. In order to do so I decided to use a regular expression match and simply assign the match (group) to a new variable.

my $powerusage=$xml->{'POWER_SUPPLIES'}[0]->{'POWER_SUPPLY_SUMMARY'}[0]->{'PRESENT_POWER_READING'}[0]->{'VALUE'};
# At this point $powerusage value is: "167 Watts"
my $powerperf = $powerusage =~ m/(\d+) [Ww]atts/i;
print "power usage $powerusage ($powerperf)\n";

Basically the $powerusage variable is using a SimpleXML function to red a specific value from the XML document (saved as $xml). This works fine and results in a string value of "167 Watts".

The $powerperf variable should only contain the actual number of wattage, without any text. I tested the following regular expression m/(\d+) [Ww]atts/i on regex101 and everything seems correct:

However instead of the expected output "power usage 167 Watts (167)", $powerperf always showed a "1" as value: "power usage 167 Watts (1)".

However when the regex is directly printed to the script's output, without saving the value to a variable, the output showed the correct value:

my $powerusage=$xml->{'POWER_SUPPLIES'}[0]->{'POWER_SUPPLY_SUMMARY'}[0]->{'PRESENT_POWER_READING'}[0]->{'VALUE'};
my $powerperf = $powerusage =~ m/(\d+) [Ww]atts/i;
print "power usage $powerusage ($powerperf)\n";
print "power usage in numbers:\n";
print $powerusage =~ m/(\d+) [Ww]atts/i;
print "\n";

Output:

power usage 175 Watts (1)
power usage in numbers:
175

Research led to a question on stackoverflow where the same problem was discussed:

I get back a '1' as the value of $link. I assume this is because it found '1' match. But how do I save the content of the match instead?

Luckily user ikegami gave a solution where the first match can be saved into a variable by putting the variable itself into parentheses.

Note the /g to get all matches. Those can't possibly be put into a scalar. You need an array. If you just want the first match [...] note the parens (and the lack of now-useless /g). You need them to call m// in list context.

By applying this knowledge, the declaration of $powerperf was adjusted:

my $powerusage=$xml->{'POWER_SUPPLIES'}[0]->{'POWER_SUPPLY_SUMMARY'}[0]->{'PRESENT_POWER_READING'}[0]->{'VALUE'};
my ($powerperf) = $powerusage =~ m/(\d+) [Ww]atts/i;
print "power usage $powerusage ($powerperf)\n";

And the output is now correct:

power usage 158 Watts (158)



Add a comment

Show form to leave a comment

Comments (newest first)

No comments yet.

RSS feed

Blog Tags:

  AWS   Android   Ansible   Apache   Apple   Atlassian   BSD   Backup   Bash   Bluecoat   CMS   Chef   Cloud   Coding   Consul   Containers   CouchDB   DB   DNS   Database   Databases   Docker   ELK   Elasticsearch   Filebeat   FreeBSD   Galera   Git   GlusterFS   Grafana   Graphics   HAProxy   HTML   Hacks   Hardware   Icinga   Influx   Internet   Java   KVM   Kibana   Kodi   Kubernetes   LVM   LXC   Linux   Logstash   Mac   Macintosh   Mail   MariaDB   Minio   MongoDB   Monitoring   Multimedia   MySQL   NFS   Nagios   Network   Nginx   OSSEC   OTRS   Observability   Office   OpenSearch   PGSQL   PHP   Perl   Personal   PostgreSQL   Postgres   PowerDNS   Proxmox   Proxy   Python   Rancher   Rant   Redis   Roundcube   SSL   Samba   Seafile   Security   Shell   SmartOS   Solaris   Surveillance   Systemd   TLS   Tomcat   Ubuntu   Unix   VMWare   VMware   Varnish   Virtualization   Windows   Wireless   Wordpress   Wyse   ZFS   Zoneminder