1

Storing grep output with spaces. I wanted to store the output of grep command (with spacing) into variable or array and print it out with the spacing as well.

File containing:

### Invoked at: Wed Dec  7 22:24:35 2022 ###

Code:

my $date = qx(grep -oP "\bInvoked at: \\K[^#]*\d" $file);
print "Date: $date\n";

Expected output:

Date: Invoked at: Wed Dec  7 22:24:35 2022
peace
  • 149
  • 7

1 Answers1

4

\b and \d should be \\b and \\d. qx literals are like qq literals, so \, $ and @ need to be escaped.

And you should get rid of \n in the print statement since the string in $date already has one, or remove the one in $date using chomp( $date );.

You also have a code injection bug in your interpolation of $file which could be solved using String::ShellQuote's shell_quote.

use String::ShellQuote qw( shell_quote );

my @cmd = ( "grep", "-oP", '\bInvoked at: \K[^#]*\d', $file_qfn );
my $cmd = shell_quote( @cmd );

my $date = 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( $date );

say $date;

Better yet, we can avoid the shell, and avoiding building a shell command.

use IPC::System::Simple qw( capturex );

my @cmd = ( "grep", "-oP", '\bInvoked at: \K[^#]*\d', $file_qfn );

my $date = capturex( @cmd );
chomp( $date );

say $date;

Buy why run a child process at all?

use File::Slurper qw( read_text );

my $file = read_text( $file_qfn );

my ( $date ) = $file =~ /\bInvoked at: ([^#]*\d)/
   or die( "Invocation date not found\n" );

say $date;
ikegami
  • 367,544
  • 15
  • 269
  • 518