http://www.perlmonks.org?node_id=1232192

thanos1983 has asked for the wisdom of the Perl Monks concerning the following question:

Hello everyone,

This should be straight forward but I am stuck and I have not find a solution to my minor problem. I have written a small script to convert mp4 to mp3 files and I am getting stuck when files contain single quote.

I know that I could use quotemeta but it escapes more characters that what I need. I only need to escape the specific character '.

Sample of code and what I have tried:

#!/usr/bin/perl use strict; use warnings; use feature 'say'; my $string = "This sting it's bothering to escape ' single characters" +; $string =~s/(\W)/\\$1/g; say $string; __END__ $ perl test.pl This\ sting\ it\'s\ bothering\ to\ escape\ \'\ single\ characters

I also found this relevant question Escaping single quote in $string. Unfortunately all proposed solutions remove the quote and I want to keep it.

Any hint is appreciated.

Seeking for Perl wisdom...on the process of learning...not there...yet!

Replies are listed 'Best First'.
Re: How to escape single quote(s) without the use of quotemeta
by hippo (Bishop) on Apr 05, 2019 at 14:43 UTC

    Is this what you are after?

    use strict; use warnings; use Test::More tests => 1; my $have = "This sting it's bothering to escape ' single characters"; my $want = "This sting it\\'s bothering to escape \\' single character +s"; $have =~ s/'/\\'/g; is $have, $want;

      Hello hippo,

      Thanks it works. I thought also about escaping the back slash character and I have tried it but it did not worked for me. I guess s and g is what I was looking for.

      Thanks again for your time and effort.

      BR / Thanos

      Seeking for Perl wisdom...on the process of learning...not there...yet!
Re: How to escape single quote(s) without the use of quotemeta
by haukex (Archbishop) on Apr 05, 2019 at 17:52 UTC

    In my experience, with this kind of question, it helps to know exactly what format is expected. First, you said "I only need to escape the specific character '", which is easily solved by hippo's suggestion of s/'/\\'/g, but later on you said "I thought also about escaping the back slash character" - so do you want to escape both backslashes and single quotes? Are there maybe any more characters? In other words, what will you be using these strings for, what API are you passing them to? That would be a good reference for the expected format.

      I agree, but I'm expecting it only to reflect the escaping rules inside a single quote.

      Inside single quotes it's only possible to escape another single quote and backslash.

      (This rule varies of course if you use q() with differing boundary characters.)

      Using Data::Dumper should be sufficient here, otherwise the OP should show us where it fails.

      We can't know which interface he is using, probably he's shelling out ... in this case it's most probably a XY problem.

      Cheers Rolf
      (addicted to the Perl Programming Language :)
      Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

Re: How to escape single quote(s) without the use of quotemeta ( q// )
by LanX (Saint) on Apr 05, 2019 at 14:57 UTC
    not sure if I understand your requirement, does q help?

    DB<2> x q(LanX' solution) 0 'LanX\' solution' DB<3> x q(LanX\' solution) 0 'LanX\\\' solution'

    edit

    DB<14> use Data::Dump qw/dd/ DB<15> dd q(LanX' solution) "LanX' solution" DB<16> dd q(LanX\' solution) "LanX\\' solution"

    If not what is your desired output?

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

      Hello LanX,

      I have also tried with q but it did not worked for me.

      The desired output would be something like:

      #!/usr/bin/perl use strict; use warnings; use feature 'say'; my $string = "It's"; say quotemeta $string; __END__ $ perl test.pl It\'s

      Thanks again for your time and effort.

      BR / Thanos

      Seeking for Perl wisdom...on the process of learning...not there...yet!
        what about the backslash, do you really want quotemetas behavior?

        DB<26> x q(It's\ ) 0 'It\'s\\ ' DB<27> x quotemeta q(It's\ ) 0 'It\\\'s\\\\\\ ' ... DB<29> x quotemeta q(It's\x) 0 'It\\\'s\\\\x'

        FWIW you can write a regex which consumes every paired backslash in an or'ed condition before replacing single quotes/backslashes.

        But a real test-cases are imperative here.

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

        update

        this shows that the input format should be well defined too

        DB<37> dd quotemeta q(It's\x\\) "It\\'s\\\\x\\\\"
Re: How to escape single quote(s) without the use of quotemeta
by johngg (Canon) on Apr 05, 2019 at 16:34 UTC

    I prefer to record the positions of the single quotes then use substr to escape them, working backwards from the end of the string. I tend to avoid double backslash confusion by using the \x5c ASCII literal, although in this simple case q{\\} would be fine.

    use 5.026; use warnings; my $string = q{This sting it's bothering to escape ' single characters +}; my @posns; push @posns, pos $string while $string =~ m{(?=')}g; substr $string, $_, 0, qq{\x5c} for reverse @posns; say $string;

    I hope this is helpful.

    Cheers,

    JohnGG

Re: How to escape single quote(s) without the use of quotemeta
by Anonymous Monk on Apr 05, 2019 at 18:52 UTC
    I have written a small script to convert mp4 to mp3 files and I am getting stuck when files contain single quote.

    You seem to be constructing command line strings and feeding them to a shell. This is complicated and best handled by already written modules, such as String::ShellQuote. Note that if you do it incorrectly, your program faces the danger of a shell injection.

    If you use list form of system (e.g. system "ffmpeg", "-loglevel", "warning", "-i", $infile, "-vn", "-aq", 5, "-acodec", "libvorbis", $outfile instead of system "ffmpeg -loglevel warning -i ".quote($infile)." -vn -aq 5 -acodec libvorbis ".quote($outfile), no shell sits between your script and the music encoding process and the risk of shell injection is averted.

      You seem to be constructing command line strings and feeding them to a shell.

      really?

Re: How to escape single quote(s) without the use of quotemeta (Data::Dumper)
by LanX (Saint) on Apr 05, 2019 at 15:54 UTC
    quotemeta is meant for regex metas which form a super-set of "string metas".

    But what about the stringyfications from Data::Dumper (single quote) or Data::Dump (double quote)?

    DB<62> use Data::Dumper qw/Dumper/ DB<63> $Data::Dumper::Terse = 1; DB<64> $x= Dumper q(It's\x\\) DB<65> print "<<<$x>>>" <<<'It\'s\\x\\' >>> DB<66> chomp $x DB<67> $x =~ s/^'(.*)'$/$1/ DB<68> print "<<<$x>>>" <<<It\'s\\x\\>>> DB<69>

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

    edit

    NB: If you wanna use $Data::Dumper::Terse think of localizing it or use the OO interface ...