3 ms·
I guess you mean something like (in Perl): while (1) { try_reading_one_more_line( $file_in ); print_last_10_lines_reverse(); sleep(
by acqq 7y ago
I guess you mean something like (in Perl):
while (1) {
try_reading_one_more_line( $file_in );
print_last_10_lines_reverse();
sleep( 1 ); # wait, in this case one second
}
and that doing on the opened file $file_in. You'd have to write both functions in the loop of course. But Perl is a real language which allows you to try reading from the point in the file you've reached the last time, without reading anything you've already read again. POSIX semantics allows you to observe that the file grew even if in the previous pass you've hit the end of file. And you even don't have to keep in memory the lines which aren't to be printed anymore.
I prefer Perl to any shell scripts, as soon as the script is more than circa 10 lines.
- Arnavion 7y ago>I guess you mean something like Yes. >But Perl is a real language which allows you to try reading from the point in the file you've reached the last time, without reading anything you've already read again. The input in this case is the stdout of a command (clog), so it's not a seekable file.
- acqq 7y ago> it's not a seekable file. The flow I've described works on non-seekable files (and pipes). After you reach the end of file in one pass, you are allowed to try to read again in the next, and the file pointer stayed on the same position if you haven't closed the file (and of course you should not close it). If the other process wrote something, the next time read will succeed. If you don't want to display the partial line before the line feed is written, you have to collect the read bytes before you read the line feed. It's all doable in Perl. The only case I've seen something of what I've described not working was some case under some non-recent version of Wine, and I don't know if they fixed that. Otherwise Perl and POSIX support everything described.
- acqq 7y agoA small demo: gen_lines.pl: #!/usr/bin/env perl $| = 1; while (1) { print "line $n\n"; $n++; sleep( 3 ); } show_10.pl: #!/usr/bin/env perl $u = 1; @lines = (); while (1) { $line = <>; push @lines, $line; shift @lines if ( scalar( @lines ) > 10 ); print "10 lines update $u:\n"; $u++; for $l ( reverse @lines ) { print $l; } sleep( 1 ); } ./gen_lines.pl | ./show_10.pl
- Arnavion 7y agoOkay, I thought you were trying to say that perl could resume reading from the last position of the file after closing and reopening it, which would require a seekable file to work. If you were referring to leaving the file open across multiple iterations, then yes that is already what I said in the first post that you responded to. It's obvious that perl can do it; any program can.
- acqq 7y ago> It's obvious that perl can do it; any program can. I'm not aware how shell scripts or awk could do that. Maybe you can explain. I knew about Perl and that's what I showed.
- Arnavion 7y agoIn awk, `"foo" | getline` spawns `foo` and reads the first line from it, or reads the next line from the previous invocation of `foo` if that hasn't been closed yet. You have to explicitly call `close("foo")` to make the next invocation of `"foo" | getline` spawn a new `foo` instead of reading another line from the previous one. In shell, you'd just move the invocation of `foo` outside the dashboard loop, ie `foo | while :; do if read -r line; then ...; fi; sleep 1; done` The hard part is not to read from the same command across multiple dashboard iterations. The hard part is detecting that there is nothing more to read from the command without blocking, so that the dashboard can continue rendering if there's no more input. As I wrote in the first post that you responded to, gawk has `PROCINFO["read_timeout"]` to help with this (`getline` will return a specific error that the script can detect and break out of the loop), but FreeBSD's awk does not, which is why I was thinking of investigating whether Perl can do it.