How do I pass $SHELL variable into a perl search a

2020-03-26 04:34发布

问题:

I have the following two commands :

value=`grep -o Logs\/.*txt\" textFILE`
perl -i -wpe's/" onclick="img=document\.getElementById\('\''img_1'\''\); img\.style\.display = \(img\.style\.display == '\''none'\'' \? '\''block'\'' : '\''none'\''\);return false"/$value/' textFILE

However, I keep on getting a Use of uninitialized value $value in concatenation (.) or string at -e line 1, <> line 56. error. Can someone tell me what I am doing wrong.

回答1:

For an example like the following:

$ value=$(uname -r)
$ perl -e 'print "$value"'

When we run Perl to execute our code here we are not sending the contents of the shell variable $value to Perl. We are sending the literal string '$value', which Perl will then try and print the Perl variable $value, which does not exist.

Here are two ways that you could correct this.

The first would be to wrap your Perl code in double quotes instead of single quotes so that $value becomes the contents of the shell variable $value instead of the literal string '$value' when sent to Perl:

$ value=$(uname -r)
$ perl -e "print '$value'"
3.13.9-generic

However when using this method if you have Perl variables along with this shell variable you will need to 'escape' the Perl variables or you'll get an error like this:

$ value=$(uname -r)
$ perl -e "$example = 'test'; print \"$value $example\";"
syntax error at -e line 1, near "="

Using \'s will correct this:

$ value=$(uname -r)
$ perl -e "\$example = 'test'; print \"$value \$example\";"
3.13.9-generic test

Secondarily, you can avoid changing the single quotes to double quotes by exporting "value" to the environment, and then accessing it through the %ENV hash already available inside your Perl program (http://perldoc.perl.org/Env.html). For example:

$ export value=$(uname -r)
$ perl -e 'print "$ENV{value}\n"'
3.13.9-generic

Be mindful of your environment that you do not accidentally overwrite some needed environment variable. Using a naming convention very specific to your work can help:

$ export MYPROGRAMNAME_KERNEL_VERSION=$(uname -r)
$ perl -e 'print "$ENV{MYPROGRAMNAME_KERNEL_VERSION}\n"'
3.13.9-generic

printenv on most Linux systems will show you the current established environment variables. You could also just use Perl to inspect %ENV.



回答2:

Putting together your two earlier questions, Why is my perl replace not working? and How do I get a selection from the output of a grep, I will once again advise you to just do it all in perl.

The following script accepts a filename as a parameter and reads it for the first value, and then edits it in place to replace the second value with the first:

use strict;
use warnings;

die "Usage: $0 Text_file\n" if @ARGV != 1;

my ($file) = @ARGV;

# Loop through file to find Value
my $value;
while (<>) {
    $value //= $1 if m{(Logs/.*?txt")};
}

die "Unable to find value in $file\n" if ! defined $value;

# Loop through file to edit
my $literal_string = q{ onclick="img=document.getElementById('img_1'); img.style.display = (img.style.display == 'none' ? 'block' : 'none');return false"};

local @ARGV = $file;
local $^I = '.bak';
while (<>) {
    s/\Q$literal_string/$value/;
    print;
}
#unlink "$file$^I"; # Uncomment if you want to delete backup