strings with formatted characters in %ARGV

Discussion in 'Perl Misc' started by mfrost8@gmail.com, Jun 25, 2007.

  1. Guest

    I thought I knew perl pretty well, but then this came up and has me
    totally stumped -- making me realize I don't understand it as well as
    I thought...

    I'm trying to pass one or more formatted (i.e. with '\n' in it)
    strings to a perl program and have them print with the formatting.
    Consider the following perl code:

    #!/usr/bin/perl
    print $ARGV[0];

    Now if I run the program as follows:

    $ ./x.pl "FOO\n\n\n"

    I get

    FOO\n\n\n$

    which I don't understand. If I set a scalar string within the program
    similarly:

    #!/usr/bin/perl
    my $foo = "FOO\n\n\n";
    print $foo;

    I get what I'd expect.

    What am I missing here? Why can't I get print/printf to honor those
    special characters when used from the command line?

    Thanks
    , Jun 25, 2007
    #1
    1. Advertising

  2. -berlin.de Guest

    <> wrote in comp.lang.perl.misc:
    > I thought I knew perl pretty well, but then this came up and has me
    > totally stumped -- making me realize I don't understand it as well as
    > I thought...
    >
    > I'm trying to pass one or more formatted (i.e. with '\n' in it)
    > strings to a perl program and have them print with the formatting.
    > Consider the following perl code:
    >
    > #!/usr/bin/perl
    > print $ARGV[0];
    >
    > Now if I run the program as follows:
    >
    > $ ./x.pl "FOO\n\n\n"
    >
    > I get
    >
    > FOO\n\n\n$


    This is discussed in the FAQ "How can I expand variables in text strings?".
    While you want to expand escape sequences and not variables, the reason
    for the behavior and the solutions are similar.

    Anno
    -berlin.de, Jun 25, 2007
    #2
    1. Advertising

  3. wrote:
    > I'm trying to pass one or more formatted (i.e. with '\n' in it)
    > strings to a perl program and have them print with the formatting.


    '\n' has nothing to do with formatting. It is a representation of a
    character, that otherwise could not by typed.

    > Now if I run the program as follows:
    > $ ./x.pl "FOO\n\n\n"
    >
    > I get
    > FOO\n\n\n$
    >
    > which I don't understand. If I set a scalar string within the program
    > similarly:
    > my $foo = "FOO\n\n\n";
    > print $foo;
    >
    > I get what I'd expect.
    >
    > What am I missing here? Why can't I get print/printf to honor those
    > special characters when used from the command line?


    You are confusing program text and data.
    my $foo = "FOO\n\n\n";
    is program source code. When interpreted the Perl interpreter will convert
    this into the text FOO followed by three newlines in whatever representation
    is needed for your OS AND THEN STORE THIS DATA ITEM. This happens as compile
    time.

    However when reading parameters from the command line Perl reads that data
    as is because it is data already, no need to interpret it.

    By a similar argument you could ask why
    ./x.pl "print 'Hello world'"
    doesn't print the text Hello World.

    jue
    Jürgen Exner, Jun 25, 2007
    #3
  4. Guest

    On Jun 25, 12:50 pm, "Jürgen Exner" <> wrote:
    > wrote:
    > > I'm trying to pass one or more formatted (i.e. with '\n' in it)
    > > strings to a perl program and have them print with the formatting.

    >
    > '\n' has nothing to do with formatting. It is a representation of a
    > character, that otherwise could not by typed.
    >
    > > Now if I run the program as follows:
    > > $ ./x.pl "FOO\n\n\n"

    >
    > > I get
    > > FOO\n\n\n$

    >
    > > which I don't understand. If I set a scalar string within the program
    > > similarly:
    > > my $foo = "FOO\n\n\n";
    > > print $foo;

    >
    > > I get what I'd expect.

    >
    > > What am I missing here? Why can't I get print/printf to honor those
    > > special characters when used from the command line?

    >
    > You are confusing program text and data.
    > my $foo = "FOO\n\n\n";
    > is program source code. When interpreted the Perl interpreter will convert
    > this into the text FOO followed by three newlines in whatever representation
    > is needed for your OS AND THEN STORE THIS DATA ITEM. This happens as compile
    > time.
    >
    > However when reading parameters from the command line Perl reads that data
    > as is because it is data already, no need to interpret it.
    >
    > By a similar argument you could ask why
    > ./x.pl "print 'Hello world'"
    > doesn't print the text Hello World.
    >
    > jue


    Huh. Interesting. I guess I got burned here by how perl usually
    understands what you want to do without having to explicitly specify
    it.

    I could see this in the case of variables in a string -- how would
    perl know what "$foo" is? But I would have thought that
    representations of special characters like '\n' would be treated
    differently.

    My assumption here would be that when running using a function like
    print that kind of assumes it's working with strings that it would
    interpret that 2-character sequence when it was invoked.

    So then this means that I have to parse out all the 2-character
    sequences myself and replace them? I read the FAQ entry that the
    previous poster sent and it seemed to use a regex to do substitutions
    on the string which then replaced the same string with itself. I
    didn't have much success bending that FAQ to do my bidding. I tried a
    few things, but the last thing I tried was simply

    my $foo = $ARGV[0];
    $foo =~ s/(\\n)/$1/g;
    print $foo;

    Which didn't seem to change anything.

    What do I need to do to make this work the way I expect it to?

    Thanks very much for your time and input.
    , Jun 25, 2007
    #4
  5. Guest

    On Jun 25, 2:51 pm, wrote:
    > On Jun 25, 12:50 pm, "Jürgen Exner" <> wrote:
    > I tried a
    > few things, but the last thing I tried was simply
    >
    > my $foo = $ARGV[0];
    > $foo =~ s/(\\n)/$1/g;
    > print $foo;
    >
    > Which didn't seem to change anything.
    >
    > What do I need to do to make this work the way I expect it to?
    >
    > Thanks very much for your time and input.


    Whoops. I meant to say that I'd tried

    my $foo = $ARGV[0];
    eval { $foo =~ s/(\\n)/$1/eeg };
    print $foo;

    and that didn't yield anything different.

    Thanks
    , Jun 25, 2007
    #5
  6. On Mon, 25 Jun 2007 09:33:13 -0700, wrote:

    >Subject: strings with formatted characters in %ARGV


    Nope, there's nothing useful in the hash slot of *ARGV that I know of.

    >I'm trying to pass one or more formatted (i.e. with '\n' in it)
    >strings to a perl program and have them print with the formatting.


    It's not "formatted". It just contains "\n"s. (Not '\n's, BTW, at
    least when speaking Perl.)


    >Consider the following perl code:
    >
    > #!/usr/bin/perl
    > print $ARGV[0];
    >
    >Now if I run the program as follows:
    >
    > $ ./x.pl "FOO\n\n\n"
    >
    >I get
    >
    > FOO\n\n\n$


    That's to be expected. That's what the *shell* is giving to your Perl
    program. You have to ask the shell to pass in real newlines, as
    opposed to whatever else:

    kirk:~ [22:08:08]$ perl -le 'print $ARGV[0]' 'FOO
    >
    >
    > '

    FOO



    kirk:~ [22:08:32]$

    >which I don't understand. If I set a scalar string within the program

    ^^^^^^
    ^^^^^^

    >similarly:
    >
    > #!/usr/bin/perl
    > my $foo = "FOO\n\n\n";
    > print $foo;
    >
    >I get what I'd expect.


    You SAID it. If you set it *within* the program, then you have the
    perl interpreter handle the thing otherwise you let the shell do so.

    >What am I missing here? Why can't I get print/printf to honor those
    >special characters when used from the command line?


    Do you want to pass a literal '\n\n\n' and have Perl interpret it as
    if it were "\n\n\n\"? The roll your own quoted stuff expansion routine
    or -if you're brave enough- use string eval: be prepared to be open to
    all sorts of security risks if doing so, though.


    Michele
    --
    {$_=pack'B8'x25,unpack'A8'x32,$a^=sub{pop^pop}->(map substr
    (($a||=join'',map--$|x$_,(unpack'w',unpack'u','G^<R<Y]*YB='
    ..'KYU;*EVH[.FHF2W+#"\Z*5TI/ER<Z`S(G.DZZ9OX0Z')=~/./g)x2,$_,
    256),7,249);s/[^\w,]/ /g;$ \=/^J/?$/:"\r";print,redo}#JAPH,
    Michele Dondi, Jun 25, 2007
    #6
  7. On Mon, 25 Jun 2007 11:51:06 -0700, wrote:

    >I could see this in the case of variables in a string -- how would
    >perl know what "$foo" is? But I would have thought that
    >representations of special characters like '\n' would be treated
    >differently.


    The rationale is that one wants to do so rarely enough that it'd
    better *not* be the default and that there's an easy enough way to do
    so when needed.

    >So then this means that I have to parse out all the 2-character
    >sequences myself and replace them? I read the FAQ entry that the
    >previous poster sent and it seemed to use a regex to do substitutions
    >on the string which then replaced the same string with itself. I


    With an /ee modifier. But it is string eval, and thus evil(TM).
    Fortunately ou don't need it yourself...

    >didn't have much success bending that FAQ to do my bidding. I tried a
    >few things, but the last thing I tried was simply
    >
    >my $foo =3D $ARGV[0];
    >$foo =3D~ s/(\\n)/$1/g;


    Try

    $foo =~ s/\\n/\n/g;

    (No need to capture)

    >print $foo;
    >
    >Which didn't seem to change anything.


    In fact you substituted what you matched with... er... well... itself!


    Michele
    --
    {$_=pack'B8'x25,unpack'A8'x32,$a^=sub{pop^pop}->(map substr
    (($a||=join'',map--$|x$_,(unpack'w',unpack'u','G^<R<Y]*YB='
    ..'KYU;*EVH[.FHF2W+#"\Z*5TI/ER<Z`S(G.DZZ9OX0Z')=~/./g)x2,$_,
    256),7,249);s/[^\w,]/ /g;$ \=/^J/?$/:"\r";print,redo}#JAPH,
    Michele Dondi, Jun 25, 2007
    #7
  8. <> wrote:
    > On Jun 25, 12:50 pm, "Jürgen Exner" <> wrote:
    >> wrote:
    >> > I'm trying to pass one or more formatted (i.e. with '\n' in it)
    >> > strings to a perl program and have them print with the formatting.

    >>
    >> '\n' has nothing to do with formatting. It is a representation of a
    >> character, that otherwise could not by typed.
    >>
    >> > Now if I run the program as follows:
    >> > $ ./x.pl "FOO\n\n\n"

    >>
    >> > I get
    >> > FOO\n\n\n$

    >>
    >> > which I don't understand. If I set a scalar string within the program
    >> > similarly:
    >> > my $foo = "FOO\n\n\n";
    >> > print $foo;

    >>
    >> > I get what I'd expect.

    >>
    >> > What am I missing here?



    A fundamental tenant of computer science, namely the difference
    between what is "code" and what is "data".

    "code" and "data" are treated differently.

    Perl source is "code" while command line arguments are "data".


    >> > special characters when used from the command line?



    Because those 2 characters are NOT special in "data".


    >> You are confusing program text and data.



    Oh. Jürgen has already pointed out what you are missing here. :)



    > I would have thought that
    > representations of special characters like '\n' would be treated
    > differently.



    If they are in "data", then they are not "special".


    > My assumption here would be that when running using a function like
    > print that kind of assumes it's working with strings



    print 10;

    no string there (until perl makes it into one).


    > that it would
    > interpret that 2-character sequence when it was invoked.



    Interpreting backslash escapes such as \n is not related to
    print, or any other, function.

    Interpreting backslash escapes is related to double quoted
    strings in "code".


    > So then this means that I have to parse out all the 2-character
    > sequences myself and replace them?



    Yes.


    > I read the FAQ entry that the
    > previous poster sent and it seemed to use a regex to do substitutions
    > on the string which then replaced the same string with itself. I
    > didn't have much success bending that FAQ to do my bidding. I tried a
    > few things, but the last thing I tried was simply
    >
    > my $foo = $ARGV[0];
    > $foo =~ s/(\\n)/$1/g;
    > print $foo;
    >
    > Which didn't seem to change anything.



    It changed it to be what it already was.


    > What do I need to do to make this work the way I expect it to?



    $foo =~ s/\\n/\n/g;


    --
    Tad McClellan
    email: perl -le "print scalar reverse qq/moc.noitatibaher\100cmdat/"
    Tad McClellan, Jun 25, 2007
    #8
  9. <> wrote:
    > On Jun 25, 2:51 pm, wrote:


    > Whoops. I meant to say that I'd tried
    >
    > my $foo = $ARGV[0];
    > eval { $foo =~ s/(\\n)/$1/eeg };
    > print $foo;
    >
    > and that didn't yield anything different.



    Let's analyse how that happened.

    The first 'e' has this code to evaluate:

    $1

    so it replaces the variable name with the variable's value, leaving
    this for the second 'e' to evaluate:

    \n

    That is a bareword string, it evaluates to itself.

    Then the outer eval sees a 3 (the return value from s/// is the
    number of substitutions it did), and so is useless here.


    --
    Tad McClellan
    email: perl -le "print scalar reverse qq/moc.noitatibaher\100cmdat/"
    Tad McClellan, Jun 26, 2007
    #9
  10. Guest

    On Jun 25, 6:56 pm, Tad McClellan <> wrote:
    > <> wrote:
    >
    > > What do I need to do to make this work the way I expect it to?

    >
    > $foo =~ s/\\n/\n/g;
    >
    > --
    > Tad McClellan
    > email: perl -le "print scalar reverse qq/moc.noitatibaher\100cmdat/"


    Thanks much for the many responses I received. I genuinely appreciate
    you folks taking the time time help me out with this.

    After my last post, I played around some more and came up with the
    code shown above that I had found worked as well. However, what I was
    hoping for was something more general purpose that allowed me to
    replace all or at least multiple metacharacters in one go. I'm not
    quite able to come up with something that will work here. I've tried

    $foo =~ s/(\\[nrt])/$1/eeg;

    which yields a bunch of

    Use of uninitialized value in substitution iterator at ...

    lines. It appears to me that I'm not making a match there, but I'm
    not sure why. If it's data, then perl should just see '\t' as 2
    characters.

    In this case, I'm wondering if I need the eval's in the regex. If I
    drop them, however, I don't get the errors, but I get the same output
    repeated (i.e. no substitutions).

    Mark
    , Jun 26, 2007
    #10
  11. wrote:
    > On Jun 25, 6:56 pm, Tad McClellan <> wrote:
    >> <> wrote:
    >>
    >>> What do I need to do to make this work the way I expect it to?

    >>
    >> $foo =~ s/\\n/\n/g;
    >>
    >> --
    >> Tad McClellan
    >> email: perl -le "print scalar reverse qq/moc.noitatibaher\100cmdat/"

    >
    > Thanks much for the many responses I received. I genuinely appreciate
    > you folks taking the time time help me out with this.
    >
    > After my last post, I played around some more and came up with the
    > code shown above that I had found worked as well. However, what I was
    > hoping for was something more general purpose that allowed me to
    > replace all or at least multiple metacharacters in one go. I'm not
    > quite able to come up with something that will work here. I've tried
    >
    > $foo =~ s/(\\[nrt])/$1/eeg;
    >
    > which yields a bunch of
    >
    > Use of uninitialized value in substitution iterator at ...


    If you really want to do it that way, something like the following
    should work:

    #!/usr/bin/perl

    use strict;

    my $foo = join (' ', @ARGV);

    $foo =~ s/\\([nrt])/"qq{\\$1}"/gee;

    print qq{"$foo"\n};

    __END__


    __OUTPUT__
    ./foo.pl '1 2\n3'
    "1 2
    3"

    Note, I noticed that if I passed the arguements without any quoting
    (./foo.pl 1 2\n3) the "\" would get stripped (I'm guessing my the
    shell - linux, bash) so perl only sees '1 2n3'... why does the slash get
    stripped?
    Clenna Lumina, Jun 26, 2007
    #11
  12. <> wrote:
    > On Jun 25, 6:56 pm, Tad McClellan <> wrote:
    >> <> wrote:
    >>
    >> > What do I need to do to make this work the way I expect it to?

    >>
    >> $foo =~ s/\\n/\n/g;
    >>
    >> --
    >> Tad McClellan
    >> email: perl -le "print scalar reverse qq/moc.noitatibaher\100cmdat/"



    [ it is bad form to quote .sigs (unless you are commenting on the .sig)]

    > However, what I was
    > hoping for was something more general purpose that allowed me to
    > replace all or at least multiple metacharacters in one go. I'm not
    > quite able to come up with something that will work here.



    I'd list the chars to be translated in a hash, and then look
    them up in the s///


    -----------------
    #!/usr/bin/perl
    use warnings;
    use strict;

    my %chars = (
    n => "\n",
    r => "\r",
    t => "\t",
    );
    my $foo = 'foo\tbar\nbaz\n';

    $foo =~ s/\\([nrt])/$chars{$1}/g;

    print $foo;
    -----------------


    --
    Tad McClellan
    email: perl -le "print scalar reverse qq/moc.noitatibaher\100cmdat/"
    Tad McClellan, Jun 27, 2007
    #12
  13. On Tue, 26 Jun 2007 14:12:55 -0700, "Clenna Lumina"
    <> wrote:

    >Note, I noticed that if I passed the arguements without any quoting
    >(./foo.pl 1 2\n3) the "\" would get stripped (I'm guessing my the
    >shell - linux, bash) so perl only sees '1 2n3'... why does the slash get


    Yes, it's the shell.

    >stripped?


    Because the shell does so. It has it's own backslash quoting, e.g. to
    quote a bare single quote. But it doesn't handle special charachters.
    We have to live with that. Period.


    Michele
    --
    {$_=pack'B8'x25,unpack'A8'x32,$a^=sub{pop^pop}->(map substr
    (($a||=join'',map--$|x$_,(unpack'w',unpack'u','G^<R<Y]*YB='
    ..'KYU;*EVH[.FHF2W+#"\Z*5TI/ER<Z`S(G.DZZ9OX0Z')=~/./g)x2,$_,
    256),7,249);s/[^\w,]/ /g;$ \=/^J/?$/:"\r";print,redo}#JAPH,
    Michele Dondi, Jun 27, 2007
    #13
  14. Michele Dondi wrote:
    > On Tue, 26 Jun 2007 14:12:55 -0700, "Clenna Lumina"
    > <> wrote:
    >
    >> Note, I noticed that if I passed the arguements without any quoting
    >> (./foo.pl 1 2\n3) the "\" would get stripped (I'm guessing my the
    >> shell - linux, bash) so perl only sees '1 2n3'... why does the slash
    >> get

    >
    > Yes, it's the shell.
    >
    >> stripped?

    >
    > Because the shell does so. It has it's own backslash quoting, e.g. to
    > quote a bare single quote. But it doesn't handle special charachters.
    > We have to live with that.


    I had some how forgot the shell handles foward slashes like that. It
    seems youy can simply escape them too as an alternative to quoting
    (./foo.pl 1 2\\n3), if one really wanted to.

    --
    CL
    Clenna Lumina, Jun 27, 2007
    #14
    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. Bret

    char **argv vs. char* argv[]

    Bret, Aug 31, 2003, in forum: C Programming
    Replies:
    21
    Views:
    4,557
    Richard Heathfield
    Sep 3, 2003
  2. David
    Replies:
    10
    Views:
    5,922
    Richard Heathfield
    Sep 15, 2003
  3. Hal Styli
    Replies:
    14
    Views:
    1,613
    Old Wolf
    Jan 20, 2004
  4. =?ISO-8859-1?Q?Thomas_N=FCcker?=

    sys.argv[0] - 'module' object has no attribute 'argv'

    =?ISO-8859-1?Q?Thomas_N=FCcker?=, Jun 30, 2003, in forum: Python
    Replies:
    0
    Views:
    885
    =?ISO-8859-1?Q?Thomas_N=FCcker?=
    Jun 30, 2003
  5. jab3

    char **argv & char *argv[]

    jab3, Dec 4, 2004, in forum: C Programming
    Replies:
    5
    Views:
    650
    Chris Torek
    Dec 8, 2004
Loading...

Share This Page