Handling external data

Discussion in 'Perl Misc' started by Larry W. Virden, Mar 4, 2009.

  1. 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.
    Larry W. Virden, Mar 4, 2009
    #1
    1. Advertising

  2. Larry W. Virden

    ccc31807 Guest

    On Mar 4, 8:00 am, "Larry W. Virden" <> wrote:
    > 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
    ccc31807, Mar 4, 2009
    #2
    1. Advertising

  3. Larry W. Virden wrote:
    > 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);

    --
    Gunnar Hjalmarsson
    Email: http://www.gunnar.cc/cgi-bin/contact.pl
    Gunnar Hjalmarsson, Mar 4, 2009
    #3
  4. 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
    Krishna Chaitanya, Mar 4, 2009
    #4
  5. Larry W. Virden <> wrote:


    > $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";


    --
    Tad McClellan
    email: perl -le "print scalar reverse qq/moc.noitatibaher\100cmdat/"
    Tad J McClellan, Mar 4, 2009
    #5
  6. On Mar 4, 8:31 am, Tad J McClellan <> wrote:

    >
    >     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.
    Larry W. Virden, Mar 4, 2009
    #6
  7. Ben Morrow wrote:
    > Quoth Gunnar Hjalmarsson <>:
    >> Try:
    >>
    >> my @args = ("mycommand", "arg1='abc'", "arg2='123 456'", $message);
    >> system(@args);

    >
    > You don't want the single quotes.


    True. Thanks for the correction.

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


    Must be. ;-)

    --
    Gunnar Hjalmarsson
    Email: http://www.gunnar.cc/cgi-bin/contact.pl
    Gunnar Hjalmarsson, Mar 4, 2009
    #7
  8. Ben Morrow <> wrote:
    >
    > Quoth Gunnar Hjalmarsson <>:
    >>
    >> Try:
    >>
    >> my @args = ("mycommand", "arg1='abc'", "arg2='123 456'", $message);
    >> system(@args);

    >
    > 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".


    --
    Tad McClellan
    email: perl -le "print scalar reverse qq/moc.noitatibaher\100cmdat/"
    Tad J McClellan, Mar 4, 2009
    #8
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Neo Geshel
    Replies:
    2
    Views:
    729
    Neo Geshel
    Nov 17, 2005
  2. Scott Allen
    Replies:
    8
    Views:
    10,933
    Scott Allen
    May 2, 2004
  3. mathieu
    Replies:
    1
    Views:
    277
  4. Mark Tarver
    Replies:
    22
    Views:
    1,301
    J Kenneth King
    Apr 26, 2009
  5. Mellow Crow
    Replies:
    6
    Views:
    418
    Richard Cornford
    Nov 4, 2005
Loading...

Share This Page