Backticks with single quote inside single quotes

J

john.d.russell

I have a problem that ultimately seems to be a shell problem, but since
I could work around it in the shell but not in Perl, this seems like
the most likely group.

Let's say I've got a file with a single quote in its name, e.g.
Foo'Bar. I want to include this filename inside a command invoked
through backticks.

print `ls -l 'Foo\'Bar'`;

This produces the error:

sh: -c: line 1: unexpected EOF while looking for matching `''

(Which is extra confusing because it looks like the message is trying
to emulate curly quotes by enclosing the looked-for single-quote
character with ` on one side and ' on the other.)

Doing away with backticks doesn't work. system() gives the same error:

print system("ls -l 'Foo\'Bar'");

The same thing happens when issuing that exact command in the shell,
but there I'm free to swap in double quotes. In the actual scenario
that I've boiled down to this one-liner, I'm constructing a more
elaborate string literal and interpolating a variable in a certain
spot, and that variable's value might or might not have a single quote
embedded in it. So I'm looking for some way to escape the variable's
value so that it can be substituted without triggering this error when
the resulting string is passed to the shell.

I'm running on OS X 10.4, with Perl 5.8.6. I've verified that both
pdksh and bash give the same error when issuing the command there.

I've searched the web and this group, but haven't found an example or
discussion of this same combination of quoting, backticking, and
escaping.

Thanks,
John
 
D

Denver

John said:
... since I could work around it in the shell

Since we all are not familiar with OS X, could you tell us this workaround?

Did you try the obvious escaping of the escape?
print `ls -l 'Foo\\'Bar'`;
 
D

Denver

John said:
... since I could work around it in the shell

Because not all of us are familiar with OS X, could you tell us this workaround?

Did you try the obvious escaping of the escape?
print `ls -l 'Foo\\\'Bar'`;
 
A

A. Sinan Unur

(e-mail address removed) wrote in @j33g2000cwa.googlegroups.com:
Let's say I've got a file with a single quote in its name, e.g.
Foo'Bar. I want to include this filename inside a command invoked
through backticks.

print `ls -l 'Foo\'Bar'`;

This produces the error:

sh: -c: line 1: unexpected EOF while looking for matching `''

Then enclose the file name in double quotes.

asu1@Aardvark /cygdrive/c/DOCUME~1/asu1/LOCALS~1/Temp/t
$ ls -l
total 1
-rw-r--r-- 1 asu1 None 0 Apr 15 18:48 Foo'Bar
-rwxr-xr-x 1 asu1 None 78 Apr 15 18:53 t.pl

asu1@Aardvark /cygdrive/c/DOCUME~1/asu1/LOCALS~1/Temp/t
$ cat t.pl
#!/usr/bin/perl

use strict;
use warnings;

print qx{ls -l "Foo\'Bar"};

asu1@Aardvark /cygdrive/c/DOCUME~1/asu1/LOCALS~1/Temp/t
$ ./t.pl
-rw-r--r-- 1 asu1 None 0 Apr 15 18:48 Foo'Bar

Sinan
--
A. Sinan Unur <[email protected]>
(remove .invalid and reverse each component for email address)

comp.lang.perl.misc guidelines on the WWW:
http://augustmail.com/~tadmc/clpmisc/clpmisc_guidelines.html
 
D

Denver

John said:
Doing away with backticks doesn't work. system() gives the same error:
print system("ls -l 'Foo\'Bar'");

The same thing happens when issuing that exact command in the shell,
but there I'm free to swap in double quotes.

In perl you are free to swap in all the quotes you could ever need.
What happens with print system(qx(ls -l "Foo'Bar"));?
 
P

Peter J. Holzer

Let's say I've got a file with a single quote in its name, e.g.
Foo'Bar. I want to include this filename inside a command invoked
through backticks.

print `ls -l 'Foo\'Bar'`;

This produces the error:

sh: -c: line 1: unexpected EOF while looking for matching `'' [...]
Doing away with backticks doesn't work. system() gives the same
error:

print system("ls -l 'Foo\'Bar'");

Try

print system("ls", "-l", "Foo'Bar");

or, since you were obviously interested in the output of ls:

open(P, '-|', "ls", "-l", "Foo'Bar") or die "cannot invoke ls: $!";
while (<P>) {
print;
}

Rule of thumb: Never use backticks or the single-argument form of system
unless you *know* that the command already is a proper command for your
shell. Especially don't do it if it involves filenames entered by the
user or read from directories which the user can write.

(This gets more complicated if you also need pipes and I/O redirection
in the command you want to invoke - you can then either invoke the shell
directly or do all of it in Perl)

hp
 
J

john.d.russell

Yes, I tried zero, one, two, and three backslashes.

The workaround I referred to (which another poster also suggested) was
to use double instead of single quotes around the command argument.
However, this doesn't work in my _real_ case because the actual command
there is something like:

`osascript -e '
tell application "iTunes"
set track_list to (every track of playlist "Library" whose artist is
"$artist")
....many more lines...
'`;

This is an OS X-specific command that runs an Applescript, analogous to
doing 'perl -e'.

I use single quotes around the lengthy argument to avoid having to
escape every instance of double quotes inside the long string literal.
There are many instances of double quotes in the embedded script, and
no other instances of single quotes -- except in the rare case where an
artist name has an apostrophe, for example "Jane's Addiction". So I
would like to keep all the surrounding quoting conventions if possible,
not split the entire script into a list of individual words, and just
find a transformation to do on the value of $artist so that it doesn't
give an error if it contains a single quote.

Thanks,
John
 
B

Brian Wakem

I have a problem that ultimately seems to be a shell problem, but since
I could work around it in the shell but not in Perl, this seems like
the most likely group.

Let's say I've got a file with a single quote in its name, e.g.
Foo'Bar. I want to include this filename inside a command invoked
through backticks.

print `ls -l 'Foo\'Bar'`;

This produces the error:

sh: -c: line 1: unexpected EOF while looking for matching `''

(Which is extra confusing because it looks like the message is trying
to emulate curly quotes by enclosing the looked-for single-quote
character with ` on one side and ' on the other.)

Doing away with backticks doesn't work. system() gives the same error:

print system("ls -l 'Foo\'Bar'");


Others have shown you how to do it properly. You can also escape it like
this:

print `ls -l 'Foo'\''Bar'`;
 
X

xhoster

Yes, I tried zero, one, two, and three backslashes.

The workaround I referred to (which another poster also suggested) was
to use double instead of single quotes around the command argument.
However, this doesn't work in my _real_ case because the actual command
there is something like:

So then, it is in fact not a workaround. If you find a *real* workaround
for the shell, you can than adapt it to perl.

My shell provides no way to escape a ' inside '', because all characters
other than ' and ! are considered literally, so \ is just a \. Maybe that
is your problem. So I have to close the single quotes, give an escaped ',
then re-open the single quotes.

## See what the shell would see:
print "echo 'foo'\\''bar'"
__END__
echo 'foo'\''bar'

## that looked OK, now actually do it:
print `echo 'foo'\\''bar'`
__END__
foo'bar


But rather thatn this, I would probably by-pass all of the shell
interpretation by using the 4+ argument form of the pipe-open as
Mr. Holzer suggests.

Xho
 
A

Anno Siegel

Yes, I tried zero, one, two, and three backslashes.

The workaround I referred to (which another poster also suggested) was
to use double instead of single quotes around the command argument.
However, this doesn't work in my _real_ case because the actual command
there is something like:

`osascript -e '
tell application "iTunes"
set track_list to (every track of playlist "Library" whose artist is
"$artist")
...many more lines...
'`;

You don't seem to do anything with the return value of the backticks.
Do you need it? Otherwise, use system() instead of backticks.
This is an OS X-specific command that runs an Applescript, analogous to
doing 'perl -e'.

It would have been nice if you had given a runnable example of an
osascript text.
I use single quotes around the lengthy argument to avoid having to
escape every instance of double quotes inside the long string literal.
There are many instances of double quotes in the embedded script, and
no other instances of single quotes -- except in the rare case where an
artist name has an apostrophe, for example "Jane's Addiction". So I
would like to keep all the surrounding quoting conventions if possible,
not split the entire script into a list of individual words, and just
find a transformation to do on the value of $artist so that it doesn't
give an error if it contains a single quote.

Perl has many quoting mechanisms, use the one(s) that are appropriate for
your purpose. Also, if you have a situation where quotes must be passed
to an external program, avoid interpolating a shell. So build the
components of the command, then use the list form of system() to
run the command without an intervening shell.

Something like this:

# set the artist
my $artist = 'Phil Ochs';

# build the applescript text
my $applescript = <<EOA;
tell application "iTunes"
set track_list to (every track of playlist "Library" whose artist is "$artist")
end tell
EOA

# construct the system command
my @cmd = ( qw( osascript -e), $applescript);

# run it
system @cmd and die "boo";

If you actually want the output of the command, instead of using backticks,
use open, which also allows you to specify the command as a list and
avoid the shell:

open my $script, '-|', @cmd;
my $ans;
$ans .= $_ while <$script>;
close $script or die "bah";

Anno
 

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,968
Messages
2,570,154
Members
46,702
Latest member
LukasConde

Latest Threads

Top