Handling external data

  • Thread starter Larry W. Virden
  • Start date
L

Larry W. Virden

In a small application I am seeing the following. The program uses DBI
to fetch rows of information such as first and last names, then uses
the system() call to pass the information like this:

$message = "$first_name $last_name phone number: $phone";

system("mycommand arg1='abc' arg2='123 456' details='$message'");

While it works for most cases, this morning I hit the error
mycommand warning: the parameter "phone" is ignored.
mycommand warning: the parameter "number:" is ignored.
mycommand warning: the parameter "1234" is ignored.
sh: : cannot execute

Turns out that the user was John O'Smith - the ' is causing the system
command to parse wrong.

Now, I know I can use s/'// and remove the quote. But is there
anything I can do to get the ' to pass through unscathed?

I tried, for instance, using $last_name =~ s/'/\'/;
as well as s/'/\\'/ and s/'/\\'/ and s/'/\\\'/ and in each case, even
when I could see the \ was making it to the system command, it didn't
make it through the shell's parser.

Just wondering about alternate approaches. I tried using qq
($first_name $last_name phone number: $phone) , but that was just
bypassing things on the perl side.
 
C

ccc31807

In a small application I am seeing the following. The program uses DBI
to fetch rows of information such as first and last names, then uses
the system() call to pass the information like this:

$message = "$first_name $last_name phone number: $phone";

system("mycommand arg1='abc' arg2='123 456' details='$message'");

While it works for most cases, this morning I hit the error
mycommand warning: the parameter "phone" is ignored.
mycommand warning: the parameter "number:" is ignored.
mycommand warning: the parameter "1234" is ignored.
sh: : cannot execute

Turns out that the user was John O'Smith - the ' is causing the system
command to parse wrong.

Now, I know I can use s/'// and remove the quote. But is there
anything I can do to get the ' to pass through unscathed?

I tried, for instance, using $last_name =~ s/'/\'/;
as well as s/'/\\'/ and s/'/\\'/ and s/'/\\\'/ and in each case, even
when I could see the \ was making it to the system command, it didn't
make it through the shell's parser.

Just wondering about alternate approaches. I tried using qq
($first_name $last_name phone number: $phone) , but that was just
bypassing things on the perl side.

It's not really clear to me where you are going wrong, but in general
this is a common problem. Here are four approaches that might help.
1. Use the q() operator, this won't interpolate values.
2. Escape the quote with the backslash operator.
3. Replace the quote with the ASCII octal value, \047.
4. Replace the quote with the HTML version, either &quot or &#39

As to your database read, this particular problem gave me such fits
that I converted my queries that read names to pipe delimited files:
John|O'Smith|888-555-1212
rather than
John','O'Smith','888-555-1212

Another gotcha is the space in the name, like 'van Rossum'

CC
 
G

Gunnar Hjalmarsson

Larry said:
In a small application I am seeing the following. The program uses DBI
to fetch rows of information such as first and last names, then uses
the system() call to pass the information like this:

$message = "$first_name $last_name phone number: $phone";

system("mycommand arg1='abc' arg2='123 456' details='$message'");

While it works for most cases, this morning I hit the error
mycommand warning: the parameter "phone" is ignored.
mycommand warning: the parameter "number:" is ignored.
mycommand warning: the parameter "1234" is ignored.
sh: : cannot execute

Turns out that the user was John O'Smith - the ' is causing the system
command to parse wrong.

Now, I know I can use s/'// and remove the quote. But is there
anything I can do to get the ' to pass through unscathed?

I tried, for instance, using $last_name =~ s/'/\'/;
as well as s/'/\\'/ and s/'/\\'/ and s/'/\\\'/ and in each case, even
when I could see the \ was making it to the system command, it didn't
make it through the shell's parser.

Just wondering about alternate approaches. I tried using qq
($first_name $last_name phone number: $phone) , but that was just
bypassing things on the perl side.

Try:

my @args = ("mycommand", "arg1='abc'", "arg2='123 456'", $message);
system(@args);
 
K

Krishna Chaitanya

Hi Larry, try this out:

#!/usr/bin/perl

use warnings;
use strict;

my $first_name = "John";
my $last_name = "O'Smith";
my $phone = 123;
my $message = "$first_name $last_name phone number: $phone";
print "Original message is $message\n";
$message =~ s|'|'\\''|g;
print "New message is $message\n";
system("echo myarg1='123 456' myarg2='$message'");

Check out the following from man 1 bash :

"Enclosing characters in single quotes preserves the literal value
of each character within the quotes. A single quote may not occur
between single quotes, even when preceded by a backslash."

So you can't pass it unscathed to the shell.....the only way to
preserve the odd single quote is to break the string before and after
it as 2 separate strings and treat the odd single quote itself as a
literally interpreted string in between........which makes 3 strings
out of John O'Smith :

'John O' + \' (backslash so as to treat it as literal) + 'Smith' =
'John O'\''Smith'

[bld@BLD-RHEL5-32 perl_progs]# echo 'John O'\''Smith'
John O'Smith

HTH,
Chaitanya
 
T

Tad J McClellan

$message = "$first_name $last_name phone number: $phone";

system("mycommand arg1='abc' arg2='123 456' details='$message'");

While it works for most cases, this morning I hit the error
mycommand warning: the parameter "phone" is ignored.
mycommand warning: the parameter "number:" is ignored.
mycommand warning: the parameter "1234" is ignored.
sh: : cannot execute

Turns out that the user was John O'Smith - the ' is causing the system
command to parse wrong.

Now, I know I can use s/'// and remove the quote. But is there
anything I can do to get the ' to pass through unscathed?


Your question is really about shell quoting.

AFAICT, there is no way to escape a single quote in a single quoted shell arg.

So use double quotes instead of single quotes.


system qq/mycommand arg1='abc' arg2='123 456' details="$message"/;


Or, better, avoid the shell altogether:

system 'mycommand', 'arg1=abc', 'arg2=123 456', "details=$message";
 
L

Larry W. Virden

    system 'mycommand', 'arg1=abc', 'arg2=123 456', "details=$message";


Thank you very much. I'd tried some of the other options in this
thread, but found trying to use substituion to add backslashes to be a
bit tricky.

However, so far, this version of system invocation appears to handle
the data I was getting that was generating errors.

I really appreciate your help.
 
T

Tad J McClellan

Ben Morrow said:
You don't want the single quotes.

(Is it something in the weather today? :) )


I think so, as I made the same mistakes in both threads too...

.... but managed to correct them before hitting "send".
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,578
Members
45,052
Latest member
LucyCarper

Latest Threads

Top