Fernando
Fernando

Reputation: 1

perl $ENV does not get the value of linux bash var

The following shell script is working fine while I execute it from a Linux prompt, but when it's called by a Unix service (e.g. inetd, etc.) it doesn't recognize the $ACT_NUM variable inside the Perl script.

export ACT_NUM=$1
perl -pi -e '$v=$ENV{ACT_NUM};s/TRIGGER_VALUE" value="\d*"/TRIGGER_VALUE" value="$v"/>//' soa_triggering.xml

The soa_triggering.xml content file is

<ins:Parameter name="TRIGGER_VALUE" value="1"/>

Upvotes: 0

Views: 108

Answers (2)

Charles Duffy
Charles Duffy

Reputation: 295639

Regular expressions are insufficiently expressive to parse XML. For instance, your same value could be written out over three lines with the parameter order reversed, as:

<ins:Parameter
 value="1"
 name="TRIGGER_VALUE"/>

...or with numerous other variances (unexpected whitespace, &c). Trying to cover the corner cases -- which also include distinguishing content in CDATA and comments from actual tags -- is potentially sanity-impacting.


If you're editing XML, use an actual XML parser. One good choice is XMLStarlet:

xmlstarlet ed -i \
  -u '//*[@name="TRIGGER_VALUE"]/@value' \
  -v "$ACT_NUM" \
  soa_triggering.xml

If you know what the ins namespace points to, you can do better:

# Replace http://example.com/ins-namespace with actual value
# from xmlns:ins="..." earlier in your document
xmlstarlet ed -i -N "ins=http://example.com/ins-namespace" \
  -u '//ins:Parameter[@name="TRIGGER_VALUE"]/@value' \
  -v "$ACT_NUM" \
  soa_triggering.xml

Upvotes: 2

Sobrique
Sobrique

Reputation: 53498

I think your problem is more fundamental than expansion of $1 - I'm going to hazard a guess that the regex isn't matching - because:

$v=$ENV{ACT_NUM};s/TRIGGER_VALUE" value="\d*"/TRIGGER_VALUE" value="$v"/>//

Is actually broken syntax - you're using / as your regex separator, but you're also trying to include it in your pattern.

So if you actually run this code you get:

Useless use of numeric gt (>) in void context 

So perhaps you need to consider escaping some of your meta characters:

This works:

#!/usr/bin/env perl
use strict;
use warnings;

$ENV{ACT_NUM} = 1;

while ( <DATA> ) {
    my $v=$ENV{ACT_NUM};
    s/TRIGGER_VALUE\" value=\"\d*\"/TRIGGER_VALUE\" value=\"$v\"/;
    print;
} 

__DATA__
<ins:Parameter name="TRIGGER_VALUE" value="1"/>

But really - messing around with XML using regular expressions is an inherently bad idea.

You also might want to double check that that environment actually is being propagated. If you print $v (or $ENV{ACT_NAME}) does it actually work?

So how about instead:

#!/usr/bin/env perl
use strict;
use warnings;

use XML::Twig;

my $twig = XML::Twig->new(
   twig_handlers => {
      'ins:Parameter[@name="TRIGGER_VALUE"]' =>
        sub { $_->set_att( 'value', $ENV{ACT_NUM} ) }
   }
);
$twig->parse(
   do { local $/; <> }
)->print;

Upvotes: 6

Related Questions