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

Esteemed Monks,

I am still working on some text editing utilities, written in Perl which are able to be called from VI thus:

:1,105! Perlscript

My aim is to convert a text file I’m editing in VI into code that can be read by an ancient market research software called Quantum Without doing a lot of manual editing. (Yes, I am ashamed to admit I am not a real programmer at all, but perhaps if I learn enough doing this, I might grow up to be one someday.)

I’m using split to break the lines up into fields I can rearrange into what I need, but I’ve got “junk” in some of my fields. My questions:

1. Is there a function that allows one to take the first character off a scalar variable in the same way you’d take the last character off with chop ? For example, can I make the string -3 become just 3?

2. Is it possible to look at a scalar variable containing a string, chop off all text after, say, a question mark, and make that be the new value of the scalar, thus:

$qtext = “question text? Lots of junk after that I don’t need”

becomes

$qtext = “question text?”

It might help to see what script I'm trying to incorporate the above ideas into, so here it is:

#!/usr/bin/perl while (<>){ if (/^[SCQD]/){ ($qnum,$v,$qtext) = split("\t"); chop ($qnum); print "L $qnum\nttl$qnum. $qtext\nn10TOTAL BASE\n"; } else { ($stext,$qspec,$x) = split("[\t]"); chomp ($qspec); unless (/^$/){ print "n01$stext;c=c{$qnum}'$qspec'\n"} } }

Am I just trying to do too much here, editing line by line? Is there a better but still simple way to structure this?

Any nudges in the right direction appreciated.

NovMonk

Edit by tye to remove lots of trailing space in CODE

Replies are listed 'Best First'.
Re: Using perl interactively with VI
by TomDLux (Vicar) on Mar 11, 2004 at 16:54 UTC
    1. substr $var, 1;

      perldoc -f substr for more info, on Unix

    2. s/\?.*//

      Seearch for: a literal question mark character, followed by any number of any characters; replace all that with: nothing ( i.e., delete it )

    Proceessing input files line by line is the best way to do it, unless there are reasons for processing larger chunks. hint: most of the time, when you think you need to process larger chunks, what you really need is to find a different way of thinking about the process.

    In the then clause, you chop( $qnum ), removing the last character. Or is this supposed to be the reverse-chop, from part 1? In any case, $qtext continues to end with a newline character.

    In the else clause, you chomp( $qspec ). chomp() is like chop(), except it removes only the current $INPUT_RECORD_SEPARATOR, $/, normally "\n". $qspec can't have a newline, since it comes from the middle of a line. But $x ends with a newline.

    I would suppose using chomp() right after the while(), to trim newlines from all input.


    Update: I forgot the most important part ... You left out "use strict;", and you should localize your variables with my.

    --
    TTTATCGGTCGTTATATAGATGTTTGCA

      The regular expression also removes the question mark, which should remain.
      s/\?.*/?/
Re: Using perl interactively with VI
by jeffa (Bishop) on Mar 11, 2004 at 16:57 UTC
    How about as a one-liner?
    perl -pi -le'$_=substr($_,0,index($_,"?")+1)' file.txt
    (update: added +1 to preserve first question mark)

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)
    

      No -i switch if you call perl as a filter from an editor!

        Then what about:
        #!/usr/bin/perl -pi s/this/that/g;
        I honestly don't know how to call filters from vi ... so i don't know how to test this. But i think this should take care of the problem.

        UPDATE:
        Just figured out how to use filters in vi, that wasn't hard at all! Yes, this definetly takes care of the problem. :)

        jeffa

        L-LL-L--L-LL-L--L-LL-L--
        -R--R-RR-R--R-RR-R--R-RR
        B--B--B--B--B--B--B--B--
        H---H---H---H---H---H---
        (the triplet paradiddle with high-hat)
        
Re: Using perl interactively with VI
by ambrus (Abbot) on Mar 11, 2004 at 18:01 UTC

    I answer question 1 only. You can use this code:

    $string=~ s/(.)//s; $char= $1;
    This chops off the first character from $string, and puts it into $char.

    There's also an other solution:

    $char= substr ($string, 0, 1, "");
    which does the same.
Re: Using perl interactively with VI
by NovMonk (Chaplain) on Mar 11, 2004 at 21:36 UTC
    Update: Added "-w" and "use strict" and declared variables after rereading TomDLux's update.

    Thanks for the hints-- I got something that works And learned a lot in the process. Which is always the goal. In case anyone ever is interested in calling a Perl script from VI, here's my solution (does several things besides those ennumerated in OP):

    #!/usr/bin/perl -w use strict; my ($num,$v,$text,$qnum,$qtext,$stext,$spec,$x,$qspec); while (<>){ s/ \t/\t/g; s/9[0-9][0-9][0-9] \t/9999\t/g; s/9[0-9][0-9][0-9] /9999\t/g; if (/^[SCQD]/){ ($num,$v,$text) = split("\t"); chop ($num); $qnum=substr($_,0,index($_,".")); $qtext = substr($text,0,index($text,"?")+1); print "n03;coltxt=___\nn05TOTAL\nL $qnum\nttl$qnum. $qtext\nn1 +0TOTAL BASE\n"; } else { ($stext,$spec,$x) = split("[\t]"); chomp ($spec); $qspec = substr($spec,1,1); unless (/^$/){ print "n01$stext;c=c{$qnum}'$qspec'\n"} } } print "n03;coltxt=___\nn05TOTAL\n";

    Basically, the key is to clear out some of the less predictable junk Before the if statement, and then use substr to control the more predictable junk in the scalar variables. And then if you want to add a line or two to the end of the section you're editing, print it in after the while loop and it adds the line(s) to the file.

    Thanks again for the help.

    Pax,

    NovMonk

    ps TomDLux: You're right about the chomp ($qspec); -- it's there because it Should be the last thing on the line, but wasn't always. I knew I didn't need anything after that field, so I named an extra one to make sure that junk didn't become part of $qspec.