Issue
I am using grep to return the value for the first NAME found (which could vary from case to case) found and search for the value of NAME found. Also, would like to only have the output text after the last "/".
Example file containing
NAME = abc123
abc123 = /path/to/x456
Expected output:
x456
Code:
my $name = qx(grep -oP -m 1 "NAME = \\K(.*)" $file);
my $value = qx(grep -oP -m 1 "${name} = \\K(.*)" $file);
Solution
Using qx
would be complicated.
use File::Basename qw( basename );
use String::ShellQuote qw( shell_quote );
my $file_qfn = "...";
my $name;
{
my @cmd = ( "grep", "-oP", "-m", "1", '^NAME\s+=\s+\K(.*)', $file_qfn );
my $cmd = shell_quote( @cmd );
$name = qx($cmd);
die "Can't spawn shell: $!\n" if $? == -1;
die "Shell killed by signal ".( $? & 0x7F )."\n" ) if $? & 0x7F;
die "Shell exited with error ".( $? >> 8 )."\n" ) if $? >> 8;
chomp( $name );
}
my $value;
{
my $name_pat = quotemeta( $name );
my @cmd = ( "grep", "-oP", "-m", "1", "^$name_pat\\s+=\\s+\\K(.*)", $file_qfn );
my $cmd = shell_quote( @cmd );
$value = qx($cmd);
die "Can't spawn shell: $!\n" if $? == -1;
die "Shell killed by signal ".( $? & 0x7F )."\n" ) if $? & 0x7F;
die "Shell exited with error ".( $? >> 8 )."\n" ) if $? >> 8;
chomp( $value );
}
my $base = basename( $value );
We can avoid the shell and simplify things by using capturex
.
use File::Basename qw( basename );
use IPC::System::Simple qw( capturex );
my $file_qfn = "...";
my $name;
{
my @cmd = ( "grep", "-oP", "-m", "1", '^NAME\s+=\s+\K(.*)', $file_qfn );
$name = capturex( @cmd );
chomp( $name );
}
my $value;
{
my $name_pat = quotemeta( $name );
my @cmd = ( "grep", "-oP", "-m", "1", "^$name_pat\\s+=\\s+\\K(.*)", $file_qfn );
$value = capturex( @cmd );
chomp( $value );
}
my $base = basename( $value );
But I think the idea of spawning children for this task is distasteful.
use File::Basename qw( basename );
use File::Slurper qw( read_text );
my $file_qfn = "...";
my $file = read_text( $file_qfn );
my ( $name ) = $file =~ /^NAME\s+=\s+\K(.*)/m
or die( "Can't find `NAME` field\n" );
my ( $value ) = $file =~ /^\Q$name\E\s+=\s+\K(.*)/m
or die( "Can't find `$name` field\n" );
my $base = basename( $value );
I'd actually use something like the following:
use File::Basename qw( basename );
my $file_qfn = "...";
open( my $fh, '<', $file_qfn )
or die( "Can't open file \"$file_qfn \": $!\n" );
my %data;
while ( <$fh> ) {
chomp;
my ( $k, $v ) = split( /\s+=\s+/, $_, 2 );
$data{ $k } = $v;
}
defined( my $name = $data{ NAME } )
or die( "Can't find `NAME` field\n" );
defined( my $value = $data{ $name } )
or die( "Can't find `$name` field\n" );
my $base = basename( $value );
Answered By - ikegami Answer Checked By - Cary Denson (WPSolving Admin)