Sanjay Bangalore
Sanjay Bangalore

Reputation: 81

Complicated sed command inside Perl script

I need to run a sed command inside a Perl script. But because the sed command is complicated, it does not run inside Perl. However, the sed command runs fine in shell.

Can someone please help?

File -

cat /tmp/f1

"ABC": "abcd.com"
"Xris": [
"xyz.com"
"users": "user.com"
"id": "96444aa4b618.com"

Sed command on shell -

[]$ cat /tmp/f1 | sed  '/: \[.*$/ {s/\[//; N; s/\n//g; }'
"ABC": "abcd.com"
"XUrl": "xyz.com"
"users": "user.com"
"id": "96444aa4b618.com"
[]$

However, when this sed command is called in a Perl script, it complains. I have tried many different escape characters but it does not work. Usually it throws error -

[]$ cat script.pl
#!/usr/bin/perl
`sed -e '/: \[.*$/ {s/\[//; N; s/\n//g; }' /tmp/f1`;
[]$ ./script.pl
sed: -e expression #1, char 6: unterminated address regex
[]$

Please help with how this sed command can be run from inside a Perl script. Or is there any better way of running sed in a Perl script?

Upvotes: 0

Views: 667

Answers (3)

Sanjay Bangalore
Sanjay Bangalore

Reputation: 81

Thanks all..

Sorry there was typo in the question.

Got the sed command replaced by following and now its working fine-

while (<>)
{
    if (m/: \[.*$/)
    {
        my $next = <>;
        $_ =~ s/: \[.*\n/: /;
        $_ .= $next;
    }
    print;
}

Upvotes: 0

ikegami
ikegami

Reputation: 386676

Backticks interpolate and process escapes just like double-quotes, so

`sed -e '/: \[.*$/ {s/\[//; N; s/\n//g; }' /tmp/f1`

is the same as

`sed -e '/: [.*
{s/[//; N; s/
//g; }' /tmp/f1`

You need

use String::ShellQuote qw( shell_quote );

my $cmd = shell_quote('sed', '-e', '/: \\[.*$/ {s/\\[//; N; s/\\n//g; }', '/tmp/f1');
my $output = `$cmd`;
die("sed killed by signal ".( $? & 0x7F )."\n") if $? & 0x7F;
die("sed exited with error ".( $? >> 8 )."\n") if $? >> 8;

Of course, anything sed can do can easily be done in Perl itself. You'd be better off doing that.

Upvotes: 2

Jonathan Leffler
Jonathan Leffler

Reputation: 755026

Perl can do the transformation that you're using sed to do, almost trivially. I doubt if this is minimal Perl, but it works on the sample data, except it does not map Xris to XUrl (I assume that is a typo in the question).

#!/usr/bin/env perl

use strict;
use warnings;

while (<>)
{
    if (m/: \[.*$/)
    {
        chomp;
        my $next = <>;
        $_ =~ s/: \[.*/: /;
        $_ .= $next;
    }
    print;
}

When run on the data file from the question, the output is:

"ABC": "abcd.com"
"Xris": "xyz.com"
"users": "user.com"
"id": "96444aa4b618.com"

which is pretty much what was wanted. You can probably revise the code so that the chomp is not necessary, but you need to remove the newline at the end of $_ in the if statement:

#!/usr/bin/env perl

use strict;
use warnings;

while (<>)
{
    if (m/: \[.*$/)
    {
        my $next = <>;
        $_ =~ s/: \[.*\n/: /;
        $_ .= $next;
    }
    print;
}

Same output from the same input.

Upvotes: 3

Related Questions