# Totally stuck

Discussion in 'Perl Misc' started by David Arnold, Jun 29, 2004.

1. ### David ArnoldGuest

All,

I have a file named "new".

\backtomargin

In Exercises~\ref{exer2.9.1}--\ref{exer2.9.2}, if the given
differential equation is autonomous, identify the equilibrium
solution(s). Use a numerical solver to sketch the direction field
and superimpose the plot of the equilibrium solution(s) on the
direction field. Classify each equilibrium point as either
unstable or asymptotically stable.

\ex\label{exer2.9.1} $P'=0.05P-1000$

The spacing is intentional. Now, my perl file is saved as new.pl.

use strict;
use warnings;

# replace \backtomargin with instructions environment
my @instructions;
my $instruct_line; while (my$line=<>) {
chomp($line); if ($line=~/^\s*\\backtomargin/) {
push (@instructions,$'); while ($instruct_line=<>) {
chomp($instruct_line); if ($instruct_line=~/\\ex/) {
last;
} else {
push(@instructions,$instruct_line); } } print "\\begin{instructions}\n"; # remove blank lines from end of array while($line=pop(@instructions)) {
if ($line=~/^\s*$/) {
print "true\n";;
} else {
print "false\n";
push (@instructions,$line); last; } } # remove blank lines from the beginning of the array while($line=shift(@instructions)) {
if ($line=~/^\s+$/) {
;
} else {
unshift (@instructions,$line); last; } } print join("\n",@instructions); # empty instructions array for next pass @instructions=(); print "\\end{instructions}\n\n"; print "$instruct_line\n";

} else {
print "$line\n"; } } When I enter: perl new.pl < new I get the following output: D:\NewBook\conversion>perl new.pl < new \begin{instructions} In Exercises~\ref{exer2.9.1}--\ref{exer2.9.2}, if the given differential equation is autonomous, identify the equilibrium solution(s). Use a numerical solver to sketch the direction field and superimpose the plot of the equilibrium solution(s) on the direction field. Classify each equilibrium point as either unstable or asymptotically stable. \end{instructions} \ex\label{exer2.9.1}$P'=0.05P-1000$I am using ActiveState Perl on Win95. You might note the debugging print statements and the fact that neither "true" nor "false" shows up in the output. I am completely stuck and in need of kind pair of eyes. If you can help, it would be appreciated. Thanks. David Arnold, Jun 29, 2004 1. ### Advertisements 2. ### gnariGuest "David Arnold" <> wrote in message news:... > > The spacing is intentional. Now, my perl file is saved as new.pl. > # remove blank lines from end of array > while($line=pop(@instructions))

> if ($line=~/^\s*$/) {
> print "true\n";;
> } else {
> print "false\n";
> push (@instructions,$line); > last; > } > } > I am using ActiveState Perl on Win95. You might note the debugging > print statements and the fact that neither "true" nor "false" shows up > in the output. clearly the while() block is never executed, because$line evaluates as false the first time through ('')

maybe you want something like
pop @instructions while $instructions[-1] =~ /^\s*$/;

gnari

gnari, Jun 29, 2004

3. ### Andrew LeeGuest

On 29 Jun 2004 00:32:36 -0700, (David Arnold) wrote:

>All,
>
>I have a file named "new".
>
>\backtomargin
>
>
>In Exercises~\ref{exer2.9.1}--\ref{exer2.9.2}, if the given
>differential equation is autonomous, identify the equilibrium
>solution(s). Use a numerical solver to sketch the direction field
>and superimpose the plot of the equilibrium solution(s) on the
>direction field. Classify each equilibrium point as either
>unstable or asymptotically stable.
>
>
>
>
>
>
>\ex\label{exer2.9.1} $P'=0.05P-1000$
>
>The spacing is intentional. Now, my perl file is saved as new.pl.
>
>use strict;
>use warnings;
>
># replace \backtomargin with instructions environment
>my @instructions;
>my $instruct_line; >while (my$line=<>) {
> chomp($line); > if ($line=~/^\s*\\backtomargin/) {

But there is no space before "\backtomargin" ... so the following lines never
get executed.

> push (@instructions,$'); > while ($instruct_line=<>) {
> chomp($instruct_line); > if ($instruct_line=~/\\ex/) {
> last;
> } else {
> push(@instructions,$instruct_line); > } > } ..snip From what I can gather at a quick look, you are trying to nab everything between "\backtomarin" and "\endofinstructions". Am I correct? If so, try this : if ($line=~/^\s+\\backtomargin/) {

and put whitespace before the delimeter "\backtomargin".

Better still, use a character or string that you don't expect to find elswhere
in the testfile, such as #.

Than you can say :

if ($line=~/^\#\\backtomargin/) { .... etc. HTH Andrew Lee, Jun 29, 2004 4. ### thundergnatGuest Andrew Lee wrote: > On 29 Jun 2004 00:32:36 -0700, (David Arnold) wrote: > > >>All, >> >>I have a file named "new". >> >>\backtomargin >> >> >>In Exercises~\ref{exer2.9.1}--\ref{exer2.9.2}, if the given >>differential equation is autonomous, identify the equilibrium >>solution(s). Use a numerical solver to sketch the direction field >>and superimpose the plot of the equilibrium solution(s) on the >>direction field. Classify each equilibrium point as either >>unstable or asymptotically stable. >> >> >> >> >> >> >>\ex\label{exer2.9.1}$P'=0.05P-1000$>> >>The spacing is intentional. Now, my perl file is saved as new.pl. >> >>use strict; >>use warnings; >> >># replace \backtomargin with instructions environment >>my @instructions; >>my$instruct_line;
>>while (my $line=<>) { >> chomp($line);
>> if ($line=~/^\s*\\backtomargin/) { > > > But there is no space before "\backtomargin" ... so the following lines never > get executed. > I don't know... It looks to me like there is zero or more spaces before '\backtomargin'. Actually, I think the logic problem is the lines: > while($line=pop(@instructions)) {

and
> while($line=shift(@instructions)) { Since the first line that gets popped off of the array is a blank line, the while() short circuits and the code block never gets executed. Seems to me you are doing an awful lot of extra work chomping off newlines only to add them back in, and making arrays when you really want strings. If I was trying to do something similar, I would probably do something like: use strict; use warnings; my$instructions;
my $instruct_line; while (<>) { if ($_ =~ s/^\s*\\backtomargin//) {
$instructions =$_;
while ($instruct_line=<>) { last if ($instruct_line =~ /\\ex/);
$instructions .=$instruct_line;
}
$instructions =~ s/ *\n/\n/g; while ($instructions =~ s/\n\n\n/\n\n/) {};
$instructions =~ s/^\n+//;$instructions =~ s/\n{2,}$/\n/; print "\\begin{instructions}\n$instructions\\end{instructions}\n\n$instruct_line\n"; } else { print "$_\n";
}
}

Not knowing what your exact formatting needs were, I took a guess based
on what it /looked/ what you were trying to do.

thundergnat, Jun 29, 2004
5. ### David ArnoldGuest

gnari,

> clearly the while() block is never executed, because
> $line evaluates as false the first time through ('') > > maybe you want something like > pop @instructions while$instructions[-1] =~ /^\s*$/; Thank you very much. Your suggestion pointed to the difficulty. I am now using the following and all is working well. use strict; use warnings; # replace \backtomargin with instructions environment my @instructions; my$instruct_line;
while (my $line=<>) { chomp($line);
if ($line=~/^\s*\\backtomargin/) { push (@instructions,$');
while ($instruct_line=<>) { chomp($instruct_line);
if ($instruct_line=~/\\ex/) { last; } else { push(@instructions,$instruct_line);
}
}
print "\\begin{instructions}\n";
# remove blank lines from end of array
pop @instructions while $instructions[-1]=~/^\s*$/;
# remove blank lines from the beginning of the array
shift @instructions while $instructions[0]=~/^\s*$/;
print join("\n",@instructions);
# empty instructions array for next pass
@instructions=();
print "\n\\end{instructions}\n\n";
print "$instruct_line\n"; } else { print "$line\n";
}
}

David Arnold, Jun 29, 2004
6. ### Michele DondiGuest

On 29 Jun 2004 00:32:36 -0700, (David Arnold)
wrote:

>I have a file named "new".
>
>\backtomargin
>
>
>In Exercises~\ref{exer2.9.1}--\ref{exer2.9.2}, if the given

Huh?!? Is this clpmisc or ctt?

>The spacing is intentional. Now, my perl file is saved as new.pl.

Ah, OK, then you want to (pre-)process a text (specifically, LaTeX)
file...

>use strict;
>use warnings;

[snip]

I was under the impression that your program was overly complex for
the task it was aimed at. OTOH I was too lazy to try to understand
*exactly* what you meant to do, so from your other post I grabbed the
"working version" and I tried it on your sample. Now, if I'm not
mistaken, the following should serve your needs and is considerably
simpler:

#!/usr/bin/perl -ln

print, next unless /\\backtomargin/;
{
local $/=''; chomp(my$par=<>);
print <<EOT;
\\begin{instructions}
$par \\end{instructions} EOT } __END__ >When I enter: > >perl new.pl < new BTW: no need for '<', perl new.pl new will work! HTH, Michele -- you'll see that it shouldn't be so. AND, the writting as usuall is fantastic incompetent. To illustrate, i quote: - Xah Lee trolling on clpmisc, "perl bug File::Basename and Perl's nature" Michele Dondi, Jun 29, 2004 7. ### Trent CurryGuest thundergnat wrote: > Andrew Lee wrote: >> On 29 Jun 2004 00:32:36 -0700, (David Arnold) >> wrote: [..] >>> # replace \backtomargin with instructions environment >>> my @instructions; >>> my$instruct_line;
>>> while (my $line=<>) { >>> chomp($line);
>>> if ($line=~/^\s*\\backtomargin/) { >> >> >> But there is no space before "\backtomargin" ... so the following >> lines never get executed. >> > > I don't know... It looks to me like there is zero or more spaces > before '\backtomargin'. Correct, ^\s* optionally allows for any whitespace padding before '\backtomargin'. The person you were quoting, Andrew Lee, was mistaken To that person, I at least recommand O'Reilly's infinately useful "Perl Pocket Reference, easily avaiable at any good book or computer store. > Actually, I think the logic problem is the lines: > > > while($line=pop(@instructions)) {

>
> and
> > while($line=shift(@instructions)) { > > > Since the first line that gets popped off of the array is a blank > line, the while() short circuits and the code block never gets > executed. Seems to me both of those while's should begin like this: while(defined$line=...)
if nothing can be pop'ed ot shift'ed off anymroe, undef will be returned
instead, and THEN the loop condition will fail, which sems to be what
was desired, and not if the line was empty, but if something was
returned (aka testing if there is anything left in the array.)

--
Trent Curry -

perl -e
'($s=qq/e29716770256864702379602c6275605/)=~s!([0-9a-f]{2})!pack("h2",$1
)!eg;print(reverse("$s")."\n");' Trent Curry, Jul 1, 2004 8. ### 187Guest Michele Dondi wrote: > On 29 Jun 2004 00:32:36 -0700, (David Arnold) > wrote: > I was under the impression that your program was overly complex for > the task it was aimed at. OTOH I was too lazy to try to understand > *exactly* what you meant to do, so from your other post I grabbed the > "working version" and I tried it on your sample. Now, if I'm not > mistaken, the following should serve your needs and is considerably > simpler: > > #!/usr/bin/perl -ln > > print, next unless /\\backtomargin/; I dont udnerstand whats going on here. I thought 'next' can only be used in loops, but here you're tryign to print something? Very confusing, could you please explain what exactly is happening here? > { > local$/='';
> chomp(my $par=<>); > print <<EOT; And I don't see how you've opened the file. I thought <> read from a file passed though STDIN, but you say below "no need for '<'" but withotu that you're just passing "new" to new.pl, and not the file contends, or am I missing something here..? Thanks for any explainations you can give, aas I'm quite confused > \\begin{instructions} >$par
> \\end{instructions}
>
> EOT
> }
>
> __END__
>
>
>> When I enter:
>>
>> perl new.pl < new

>
> BTW: no need for '<',
>
> perl new.pl new
>
> will work!

187, Jul 1, 2004
9. ### Sam HoldenGuest

On Wed, 30 Jun 2004 22:31:53 -0700, wrote:
> Michele Dondi wrote:
>> On 29 Jun 2004 00:32:36 -0700, (David Arnold)
>> wrote:

>
>> I was under the impression that your program was overly complex for
>> the task it was aimed at. OTOH I was too lazy to try to understand
>> *exactly* what you meant to do, so from your other post I grabbed the
>> "working version" and I tried it on your sample. Now, if I'm not
>> mistaken, the following should serve your needs and is considerably
>> simpler:
>>
>> #!/usr/bin/perl -ln
>>
>> print, next unless /\\backtomargin/;

>
> I dont udnerstand whats going on here. I thought 'next' can only be used
> in loops, but here you're tryign to print something? Very confusing,
> could you please explain what exactly is happening here?

perldoc perlrun

And see the description of what the -n command line option that
is being passed to perl (via the -ln in the #! line) does.

>
>> {
>> local $/=''; >> chomp(my$par=<>);
>> print <<EOT;

>
> And I don't see how you've opened the file. I thought <> read from a
> file passed though STDIN, but you say below "no need for '<'" but
> withotu that you're just passing "new" to new.pl, and not the file
> contends, or am I missing something here..? Thanks for any explainations
> you can give, aas I'm quite confused

perldoc perlvar

And see the description of ARGV.

<> is equivalent to <ARGV> which manages the opening of files specified
on the command line.

--
Sam Holden

Sam Holden, Jul 1, 2004
10. ### 187Guest

Sam Holden wrote:
> On Wed, 30 Jun 2004 22:31:53 -0700, wrote:
>> Michele Dondi wrote:
>>> On 29 Jun 2004 00:32:36 -0700, (David Arnold)
>>> wrote:

>>
>>> I was under the impression that your program was overly complex for
>>> the task it was aimed at. OTOH I was too lazy to try to understand
>>> *exactly* what you meant to do, so from your other post I grabbed
>>> the "working version" and I tried it on your sample. Now, if I'm not
>>> mistaken, the following should serve your needs and is considerably
>>> simpler:
>>>
>>> #!/usr/bin/perl -ln
>>>
>>> print, next unless /\\backtomargin/;

>>
>> I dont udnerstand whats going on here. I thought 'next' can only be
>> used in loops, but here you're tryign to print something? Very
>> confusing, could you please explain what exactly is happening here?

>
> perldoc perlrun
>
> And see the description of what the -n command line option that
> is being passed to perl (via the -ln in the #! line) does.

This still deosn't explain why there is a print statement there. Seems
useles there. Can someone please clearly explain this.

187, Jul 1, 2004
11. ### Paul LalliGuest

On Thu, 1 Jul 2004, 187 wrote:

> Sam Holden wrote:
> > On Wed, 30 Jun 2004 22:31:53 -0700, wrote:
> >> Michele Dondi wrote:
> >>> On 29 Jun 2004 00:32:36 -0700, (David Arnold)
> >>> wrote:
> >>
> >>> #!/usr/bin/perl -ln
> >>>
> >>> print, next unless /\\backtomargin/;
> >>
> >> I dont udnerstand whats going on here. I thought 'next' can only be
> >> used in loops, but here you're tryign to print something? Very
> >> confusing, could you please explain what exactly is happening here?

> >
> > perldoc perlrun
> >
> > And see the description of what the -n command line option that
> > is being passed to perl (via the -ln in the #! line) does.

>
> This still deosn't explain why there is a print statement there. Seems
> useles there. Can someone please clearly explain this.

From the docs:
-n causes Perl to assume the following loop around your
program, which makes it iterate over filename arguments
somewhat like sed -n or awk:

LINE:
while (<>) {
... # your program goes here
}

-l[octnum]
enables automatic line-ending processing. It has two
separate effects. First, it automatically chomps $/ (the input record separator) when used with -n or -p. Second, it assigns "$\" (the output record separator)
to have the value of octnum so that any print
statements will have that separator added back on. If
octnum is omitted, sets "$\" to the current value of$/.

So that program is actually:

#/usr/bin/perl

$\ =$/; #because of -l
while (<>) { #because of -n
chomp; #because of -l
print; #explicitly in code
next unless /\\backtomargin/;
}
__END__

The print in the original code is printing the value of $_, which comes from reading from <>. Paul Lalli Paul Lalli, Jul 1, 2004 12. ### Paul LalliGuest On Thu, 1 Jul 2004, Paul Lalli wrote: > So that program is actually: > > #/usr/bin/perl > >$\ = $/; #because of -l > while (<>) { #because of -n > chomp; #because of -l > print; #explicitly in code > next unless /\\backtomargin/; > } > __END__ > > The print in the original code is printing the value of$_, which comes
>
> Paul Lalli
>

Whoops. That's a rather significant typo. The last two lines of the
while loop should be reversed. Wouldn't be much use otherwise.

#!/usr/bin/perl
$\ =$/; #because of -l
while (<>) { #because of -n
chomp; #because of -l
next unless /\\backtomargin/;
print; #explicitly in code
}
__END__

This actually confuses me. the original code was (effectively):
perl -ln -e 'print, next unless /\\backtomargin/;'

From what I can tell, it looks like the statement containing the print and
next is a comma-separated list being evaluated in void context. In scalar
context, the comma operator evaluates each of its operands from left to
right, discarding the return values of all but the last. Using that
logic, shouldn't the print be evaluated before the next?

Now I've run this myself and verified that it does work as desired. I'm
just confused as to *why* it runs as desired. Does the comma operator do
something different in void context? (quickly checking perldoc perlop --
nope, nothing there).

If someone can clarify for me, I'd appreciate it.

Thanks,
Paul Lalli

Paul Lalli, Jul 1, 2004
13. ### Michele DondiGuest

On Wed, 30 Jun 2004 22:31:53 -0700, "187"
<> wrote:

>> "working version" and I tried it on your sample. Now, if I'm not
>> mistaken, the following should serve your needs and is considerably
>> simpler:
>>
>> #!/usr/bin/perl -ln
>>
>> print, next unless /\\backtomargin/;

>
>I dont udnerstand whats going on here. I thought 'next' can only be used
>in loops, but here you're tryign to print something? Very confusing,

In fact we *are* in a loop. But you've already been explained this by
someone else. Here I'll add only that issuing

perl -MO=Deparse new.pl

(assuming the script was called 'new.pl') you will see what's going on
behind the scenes:

BEGIN { $/ = "\n";$\ = "\n"; }
LINE: while (defined($_ = <ARGV>)) { chomp$_;
print($_), next unless /\\backtomargin/; { local$/ = '';
chomp(my $par = <ARGV>); print "\\begin{instructions}\n$par\n\\end{instructions}\n\n";
}
}
__DATA__

>And I don't see how you've opened the file. I thought <> read from a
>file passed though STDIN, but you say below "no need for '<'" but
>withotu that you're just passing "new" to new.pl, and not the file
>contends, or am I missing something here..? Thanks for any explainations
>you can give, aas I'm quite confused

Again, you've already been told that. And the answer is in the docs,
as always, but then someone kindly pointed you to the relevant
entries.

Last, I notice only now that the OP's code contained the following
lines

if ($line=~/^\s*\\backtomargin/) { push (@instructions,$');

suggesting that "\backtomargin" may not come alone on a line, so a
slightly better approximation to what he really wants may be:

#!/usr/bin/perl -lp

next unless s/.*\\backtomargin//;
{
local $/=''; chomp(my$par=<>);
$_ .= <<EOT; \n\\begin{instructions}$par
\\end{instructions}

EOT
}

__END__

This is even somewhat simpler than the previous one and... you see?
*Apparently* not even any print() there!!

Michele
--
you'll see that it shouldn't be so. AND, the writting as usuall is
fantastic incompetent. To illustrate, i quote:
- Xah Lee trolling on clpmisc,
"perl bug File::Basename and Perl's nature"

Michele Dondi, Jul 1, 2004
14. ### Michele DondiGuest

On Thu, 1 Jul 2004 14:02:46 -0400, Paul Lalli <>
wrote:

>This actually confuses me. the original code was (effectively):
>perl -ln -e 'print, next unless /\\backtomargin/;'
>
>From what I can tell, it looks like the statement containing the print and
>next is a comma-separated list being evaluated in void context. In scalar
>context, the comma operator evaluates each of its operands from left to
>right, discarding the return values of all but the last. Using that
>logic, shouldn't the print be evaluated before the next?

It is, but only if !/\\backtomargin/, i.e. on /\\backtomargin/ it
won't print *and* it won't C<next>.

Michele
--
you'll see that it shouldn't be so. AND, the writting as usuall is
fantastic incompetent. To illustrate, i quote:
- Xah Lee trolling on clpmisc,
"perl bug File::Basename and Perl's nature"

Michele Dondi, Jul 1, 2004
15. ### Paul LalliGuest

"Michele Dondi" <> wrote in message
news:...
> On Thu, 1 Jul 2004 14:02:46 -0400, Paul Lalli <>
> wrote:
>
> >This actually confuses me. the original code was (effectively):
> >perl -ln -e 'print, next unless /\\backtomargin/;'
> >
> >From what I can tell, it looks like the statement containing the print

and
> >next is a comma-separated list being evaluated in void context. In

scalar
> >context, the comma operator evaluates each of its operands from left to
> >right, discarding the return values of all but the last. Using that
> >logic, shouldn't the print be evaluated before the next?

>
> It is, but only if !/\\backtomargin/, i.e. on /\\backtomargin/ it
> won't print *and* it won't C<next>.

Okay. I think I understand. So you're saying
perl -lne 'print, next unless /foo/'
is equivalent to
perl -lne 'do {print; next;} unless /foo/'

Is that correct? If so, then I guess my question to the original poster of
that code is what's the point of the 'next' at all? Wouldn't simply '
print unless /foo/ ' do the same thing? (that is, it would do the same
thing in the simple example posted where the line ' print, next unless
/foo/ ' is the only line in a program run with the -ln options). As 'next'
would be the last thing evaluated in the loop block, it would seem to serve
no purpose.

Am I missing something obvious?

Thank you,
Paul lalli

Paul Lalli, Jul 2, 2004
16. ### Michele DondiGuest

On Thu, 01 Jul 2004 23:50:44 GMT, "Paul Lalli" <>
wrote:

>Okay. I think I understand. So you're saying
>perl -lne 'print, next unless /foo/'
>is equivalent to
>perl -lne 'do {print; next;} unless /foo/'
>
>Is that correct? If so, then I guess my question to the original poster of

I would say so.

>that code is what's the point of the 'next' at all? Wouldn't simply '
>print unless /foo/ ' do the same thing? (that is, it would do the same
>thing in the simple example posted where the line ' print, next unless
>/foo/ ' is the only line in a program run with the -ln options). As 'next'
>would be the last thing evaluated in the loop block, it would seem to serve
>no purpose.

Indeed!

>Am I missing something obvious?

Well, I can't remember at which point the above cmd line example
popped out. But in the script that I originally posted C<next> was
*not* the last thing evaluated in the loop. So it *did* make sense...

Michele

--
you'll see that it shouldn't be so. AND, the writting as usuall is
fantastic incompetent. To illustrate, i quote:
- Xah Lee trolling on clpmisc,
"perl bug File::Basename and Perl's nature"

Michele Dondi, Jul 3, 2004