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

Hello Perl Monks, I am new.
I am attempting a one-liner that:
1. Performs a -3 caesar cipher on the string of my choosing.
2. Sends the result to the shell to be executed as a command.
How would I go about doing this? I could do this easily in other languages, but would prefer it in Perl. Please and thank you advance for any help.

Replies are listed 'Best First'.
Re: One-liner to rule them all...
by davido (Cardinal) on Jul 10, 2012 at 23:01 UTC

    Rot-N ciphers are pretty trivial in Perl, as is passing a string to the shell; hardly fodder for "ruling them all". But if you could do it easily in other languages, why are you looking for a Perl solution? What does the solution you worked out in some other language lack that you need the Perl version to do for you?

    It's fine to be new. It's fine to be curious as to how to accomplish something. It's great that you want to learn (I'm assuming). But why let us have all the fun when it's something you could do (and learn from) yourself?

    The tools you will need are tr/// (discussed in perlop), system, and the -e command line switch, discussed in perlrun. A look at perlintro may also be helpful to you.

    Since you know ahead of time what the rotation will be, you won't need to deal with dynamic construction of the transliteration. It's as straight-forward as Rot-13. After a small amount of searching you would have arrived here.


    Dave

      What I have so far after doing some research:

      tr/a-z/x-za-w/

      Now just to feed this into system() call... or backticks?
      Also, to answer your questions:
      1. I'd like this in perl since perl is essentially guaranteed to be installed on a *nix system.
      2. Learning is great and I love doing it. Perl seems kinda cool, from what I've seen since yesterday.
      3. perlop held many answers :)

        I'm assuming that you're going to set up your one-liner such that the target string is held in @ARGV (A special variable documented in perlvar). That's one simple possibility. So $ARGV[0] will hold the first string passed on the command line. To bind your transliteration operator to $ARGV[0] you use the =~ operator like this: $ARGV[0] =~ tr/a-z/x-za-w/.

        Now $ARGV[0] holds the transliterated string, and all you need to do is pass it to system, just as you would pass any parameter to any function.

        If your target string contains whitespace you will have to wrap it in quotes that your shell respects.

        I still don't understand why this is useful. It's not really a form of security, and if the goal is to hide keystrokes, it is easy to unravel. Plus any system call will still show up in the process list.


        Dave

Re: One-liner to rule them all...
by frozenwithjoy (Priest) on Jul 10, 2012 at 23:00 UTC
    Here's a hint: $string =~ tr/A-Za-z/D-ZA-Cd-za-c/;
Re: One-liner to rule them all...
by aitap (Curate) on Jul 11, 2012 at 07:28 UTC

    Another hint which may be useful:

    open SHELL,"|-","/bin/sh" || die "$!";

    This opens a filehandle pointing to the child process' STDIN. You may want to do it in the BEGIN{} block if you're running your script with #!/usr/bin/perl -n.

    Sorry if my advice was wrong.
Re: One-liner to rule them all...
by pvaldes (Chaplain) on Jul 11, 2012 at 10:39 UTC

    not an one-liner, but works anyway

    my $phrase = 'who lives in a pineapple under the sea?'; @array = split //, $phrase; for $item (@array){ my $code = ord($item)+3; print chr($code);} __END__ prints : zkr#olyhv#lq#d#slqhdssoh#xqghu#wkh#vhdB