LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   unescaping a carriage return in perl (https://www.linuxquestions.org/questions/programming-9/unescaping-a-carriage-return-in-perl-30772/)

acid_kewpie 09-20-2002 06:19 AM

unescaping a carriage return in perl
 
I need to get some info out of MPlayer, namely the stdout line that shows the current position and sync of the file and such like. Now, the thing is that this line (from looking at the c source code) terminates in a carriage return ( \r ) which results in a very handy output of this line just overwriting the last, rather than churning out screen after screen of the same info.

so now the problem comes when i wish to read it in from a perl open command, as the line doesn't come into view for me, all those eding in \n are naturally fine, but i don't get the carriage return lines, which is what i want!

Any suggestions?

TheLinuxDuck 09-20-2002 09:25 AM

There are two ways of which I can think to solve this problem.

1. Alter the line input seperator ($/) so that is is a carriage return, instead of a newline.
Code:

{ local $/ = "\r";
  while(<IN>) {
      print $_, "\n";
  }
}

This works, but could be a problem, depending on any other data being read from the input stream, since <FH> depends on $/ for determining it's seperation point (and is used by readline and chomp, as well (Programming Perl 3rd Edition p. 666)).

2. split the input at the carriage returns.

Code:

while(<IN>) {
  chomp;
  my(@return) = split(/\r/, $_);
  print "@return\n"; 
}

This will give you an array of the items read in until the first available newline.. this method works nicely, but only if the input stream isn't dumping out a whole lot of data without newlines.. if it's pushing alot of data before sending a newline, you're going to have a large array and not alot of use for it.

I am thinking that #1 will work best for you. My advice would be to only set $/ to "\r" at the very point of the code that you will be reading such a line from the input stream, and set it back to "\n" once you're done. This will allow you to also read normal lines of data from the input stream, if the need is there.

I hope this helps!

TLD

acid_kewpie 09-20-2002 10:12 AM

ahh that's great, i'd just got the same solution from someone in irc, using the second method... work's great now. actually i was just abuot to change the post entirely for a new problem...

I'm trying to handle signals better, as i need to force mencoder to exit cleanly before my script closes, so i have:
Code:

$SIG{'INT'}  = sub {
  if ($main::mencpid > 0) { kill 'INT', $main::mencpid; }
  die "BYE, Mencpid was $main::mencpid\n";
  exit 0;
};

BUT this only works correctly if i comment out BOTH the die and exit commands? i presume i really should have somje sort of exit command in there, but it stops the kill working correctly. any help? thanks.

TheLinuxDuck 09-20-2002 10:26 AM

First, the exit is unnecessary with die, because the die will terminate the script.

I don't know much about signal handling, so I would personally try to find a way to do so without using them. (=

How is mencoder started?

acid_kewpie 09-20-2002 10:33 AM

well i open it in an open command and pipe the output through a function. there's no other way to stop the program, but i need it to exit correctly as i need to ensure it builds the AVI index (mencoder is a dvd encoding program ICYDK), if it stops instantly, the files are pretty useless.

i had die and exit as they normally seem to be there in peoples examples. maybe exit is just a backup incase the die fails? that's guessing it's even possible for a die to fail...

the source is still at http://thirtythreeandathird.net/mrip/mrip but i guess i just leave it the way it is, without the die or anything...

TheLinuxDuck 09-20-2002 11:26 AM

I'm assuming that the section in question is the:
Code:

my $cmd = "mencoder -ovc lavc -lavcopts $LAVC  -oac mp3lame" .
" -lameopts $BR:br=128 -dvd $track_no $AID -o $FILE $VOP 2>
 /dev/null |";
print "$0 - Running: $cmd\n";
$main::mencpid = open(ARSE, $cmd)

:section, right?

And pretty much, you just need to loop/wait until it is finished, right? So, when:
Code:

while (<ARSE>)
{
  print "$_\n";
  /Pos:\s+(\d+\.\d)s\s+(\d*)f\s+\(\s*(\d+)%\)\s+(\d+)fps\sTrem:\s+(\d+)min\s+(\d+)mb/;
  print "$1, $2, $3, $4, $5, $6\r\n";
}

:stops receiving data, shouldn't that indicate that the program is done? So, why not simply say:
Code:

while (<ARSE>)
{
  print "$_\n";
  /Pos:\s+(\d+\.\d)s\s+(\d*)f\s+\(\s*(\d+)%\)\s+(\d+)fps\sTrem:\s+(\d+)min\s+(\d+)mb/;
  print "$1, $2, $3, $4, $5, $6\r\n";
}
close(ARSE);

After all, if it stops outputting and exits that loop, doesn't that mean the program is done doing it's job, and it's safe to exit?

I have a feeling I'm missing something.... (=

acid_kewpie 09-20-2002 11:55 AM

well no, it's a case of when the perl script is abnormally terminated, it instantly whips the carpet out from underneath mencoder, and doesn't let it tie up it's ends properly, which is essential, so i need to catch the CtrlC signal, and pass it through to mencoder properly. Anyway, that seems to be working, if a little odd. now i kill mencoder OR die depencding on wether mencpid has a value, ok for now i guess...

Brings me to yet another issue. I feel dumb asking these questions, but i guess the questions are reasonable!

so... how do i know if an open command acutally worked? my line
Code:

open (TITLE_INFO, "title_info $main::DVD_DEVICE 2> /dev/null | ") or die "error running title_info! is it on your path?\n";
doesn't work at all, and the program only dies when the lack of output falls through to somewhere else.... i know i can it from a system or such, but $? doesn't work for open.

TheLinuxDuck 09-20-2002 12:42 PM

Quote:

Originally posted by acid_kewpie
so i need to catch the CtrlC signal, and pass it through to mencoder properly.
Ok, that makes sense.. so, if your perl script traps Ctrl C, then why not just have the trapped sub set a global var, something like (untested):
Code:

my($stopped) = "no";
$SIG{INT} = sub { $stopped = "yes" };
$SIG{QUIT} = sub { $stopped = "yes" };
...
...
while (<ARSE> && $stopped ne "yes")
{
  print "$_\n";
  /Pos:\s+(\d+\.\d)s\s+(\d*)f\s+\(\s*(\d+)%\)\s+(\d+)fps\sTrem:\s+(\d+)min\s+(\d+)mb/;
  print "$1, $2, $3, $4, $5, $6\r\n";
}
close(ARSE);

I don't know if this would work, but it's a thought.. also, another thought might be to simply disable Ctrl-C'ing and such..

Quote:

Brings me to yet another issue. I feel dumb asking these questions, but i guess the questions are reasonable!

Don't feel dumb! How in the work are you supposed to learn anything if you don't ever ask questions?

Quote:


so... how do i know if an open command acutally worked? my line
Code:

open (TITLE_INFO, "title_info $main::DVD_DEVICE 2> /dev/null | ") or die "error running title_info! is it on your path?\n";
doesn't work at all, and the program only dies when the lack of output falls through to somewhere else.... i know i can it from a system or such, but $? doesn't work for open.

The 'or' in that line indicates that if the open fails, whatever follows is to be executed. So, if that open fails, the die will be processed. You can tell in the die, though, why it failed if you include a $!, which is the typical error message default variable for perl..

Code:

open (TITLE_INFO, "title_info $main::DVD_DEVICE 2> /dev/null | ") or
    die "error running title_info: $!: is it on your path?\n";

If it's not hitting the die statement, then the open was successful, and the error lies elsewhere.

acid_kewpie 09-20-2002 12:57 PM

well if i make the command deliberately wrong, e.g. try to run title_infoI_REALLY_LIKE_DOUGHNUTS instead, nothing different happens, with || OR or...

oh yeah, sorry about my variable names... i still think it's better that crappy foobar *shudder, i just use my favourite words. as for your suggestion for the while condition, well that will exit that section, however the prblem lies in sending a signal to the child process itself, not handling the output. i'm happy enough with what i've got for now though... thanks

acid_kewpie 09-20-2002 02:14 PM

AHHHHHHHH yes... the stderr redirection blocks the signals!! works fine without it....

acid_kewpie 09-20-2002 02:20 PM

but now i have stderr popping out where i don't want it... bum

ohh fixed that to. nothign to reply to!


All times are GMT -5. The time now is 01:54 PM.