user1891588
user1891588

Reputation: 21

Use of pipe within backtick command

I'm having an issue with some code and I'm wondering if anyone can assist.

Basically I'm trying to execute an isql query against a database and assign it to a scalar variable. The isql command makes use of the column seperator which is defined as the pipe symbol.

So I have it set-up as such:

my $command = "isql -S -U -s| -i";
my $isql_output = `$command`;

The isql command works in isolation but when issued as a backtick it stops at the pipe. I've tried concatenating the $command string using sub-strings, using single quotes and backslash escaping items such as -s\"\|\" to no avail. I've also tried using qx instead of backticks.

Unfortunately I'm currently using an older version of perl (v5.6.1) with limited scope for upgrade so I'm not sure if I can resolve this.

Upvotes: 2

Views: 5850

Answers (3)

reinierpost
reinierpost

Reputation: 8591

The problem is that the command is being executed through a shell. You can avoid this by passing the command and arguments in a list rather than a single string. The backtick construct does not support that, so you would need to use the open() function instead. I haven't tested the following code but it gives the idea:

my @command = (qw(isql -Sserver -Uuser -Ppassword -s| -w4096), '–i' . $file);
print join(' ', @command), "\n";
open(my $fh, '-|', @command)
  or die "failed to run isql command: $@\n";
my @isql_output = <$fh>;
close($fh);
my $isql_output = $isql_output[0]; chomp($isql_output);

If you're working with a 15 year old version of Perl (which Oracle users tend to do) I'm not sure this will all be supported. For instance, you may need to write chop instead of chomp.

UPDATE: the problem is not the Perl version, but this construct not being supported on Windows, according to the documentation. This must be qualified: I use Perl on Cygwin and it works fine there, but I don't know whether you can use Cygwin.

Upvotes: 1

citrin
citrin

Reputation: 745

Single quotes should work. Try to run test perl script:

my $cmd = "./test.sh -S -U -s '|' -i";
print `$cmd`;

With test.sh:

#!/bin/sh

echo $@

Output should be -S -U -s | -i

Upvotes: 0

user507077
user507077

Reputation:

You have to quote the | in a way that the shell does not recognize it as a special character. Two ways:

  1. Put the -s| into single quotes: '-s|'. Perl will leave single quotes inside double quoted strings alone and pass them to the shell unmodified.
  2. Escape the | with two backslashes: -s\\|. Why two? The first one is seen by Perl telling it to pass the next character through unmodified. Therefore the shell sees -s\| and does something very similar: it sees the single \ and knows not to treat the next char, |, special.

Upvotes: 4

Related Questions