I know there is echo, which writes to stdout. Is it possible to redirect echo to stderr, or is there another way to write to stderr?
It is not possible to redirect echo, but the same can be achieved by using writeLine on the stderr handle (no special imports required):
stderr.writeLine("Error: ", 42)
Documentation links:
writeLine in streams module
stderr in system module
Another way is to call writeLine. It is listed among the system Exports. The docs for echo suggest also calling flushFile as below.
writeLine(stderr, "my err")
flushFile(stderr)
This was tested with Nim 1.4.2.
Related
I have the feeling that is probably not possible:
I am trying to print on the terminal text without a new line.
I have tried process.stdout.write and npm jetty but they all seem to automatically append a new line at the end.
Is it possible to write to stdout without having an automatic newline?
Just to be clear: I am not concerned about browsers, I am only interested in UNIX/Linux writing what in C/C++ would be the equivalent of:
std::cout << "blah";
printf("blah");
process.stdout.write() does not automatically add a new line. If you post precise details about why you think it does, we can probably tell you how you are getting confused, but while console.log() does add a newline, process.stdout.write() has no frills and will not write anything you don't explicitly pass to it.
Here's a shell session providing supporting evidence:
echo 'process.stdout.write("123")' > program.js
node program.js | wc -c
3
According to this link process.stdout.write():
console.log equivalent could look like this:
console.log = function(msg) {
process.stdout.write(`${msg}\n`);
};
So process.stdout.write should meet your request...
I have a embedded linux box with perl 5.10 and a GSM modem attached.
I have written a simple perl script to read/write AT commands through the modems device file (/dev/ttyACM0).
If i write a simle command like "ATZ\r" to the modem and wait for a response I receive very odd data like "\n\n\nATZ\n\n0\n\nOK\n\n\n\n\nATZ\n\n\n\n..." and the data keeps coming in. It almost seems like the response is garbled up with other data.
I would expect something like "ATZ\nOK\n" (if echo is enabled).
If i send the "ATZ" command manually with e.g. minicom everything works as expected.
This leads me to think it might be some kind of perl buffering issue, but that's only guessing.
I open the device in perl like this (I do not have Device::Serialport on my embedded linux perl installation):
open(FH, "+<", "/dev/ttyACM0") or die "Failed to open com port $comport";
and read the response one byte at a time with:
while(1) {
my $response;
read(FH, $response, 1);
printf("hex response '0x%02X'\n", ord $response);
}
Am I missing some initialization or something else to get this right?
Regards
Klaus
I don't think you need the while loop. This code should send the ATZ command, wait for the response, then print the response:
open(FH, "+>", "/dev/ttyACM0") or die "Failed to open com port $comport";
print FH ("ATZ\n");
$R = <FH>;
print $R;
close(FH);
It may be something to do with truncation. Try changing "+>" into "+<".
Or it may be something to do with buffering, try unbuffering output after your open():
select((select(FH), $| = 1)[0]);
Thanks for your answer. Although not the explicit answer to my question it certainly brought me on the right track.
As noted by mti2935 this was indeed not a perl problem, but a mere tty configuration problem.
Using the "stty" command with the following parameters set my serial port in the "expected" mode:
-opost: Disable all output postprocessing
-crnl: Do not translate CR to NL
-onlcr: Do not translate NL to CR NL
-echo: Do not echo input (having this echo enabled and echo on the modem itself gave me double echoes resulting in odd behaviour in my script)
It is also possible to use the combination setting "raw" to set all these parameters the correct way.
-
I am somewhat familiar with various ways of calling a script from another one. I don't really need an overview of each, but I do have a few questions. Before that, though, I should tell you what my goal is.
I am working on a perl/tk program that: a) gathers information and puts it in a hash, and b) fires off other scripts that use the info hash, and some command line args. Each of these other scripts are available on the command line (using another command-line script) and need to stay that way. So I can't just put all that into a module and call it good.I do have the authority to alter the scripts, but, again, they must also be usable on the command line.
The current way of calling the other script is by using 'do', which means I can pass in the hash, and use the same version of perl (I think). But all the STDOUT (and STDERR too, I think) goes to the terminal.
Here's a simple example to demonstrate the output:
this_thing.pl
#!/usr/bin/env perl
use strict;
use warnings;
use utf8;
use Tk;
my $mw = MainWindow->new;
my $button = $mw->Button(
-text => 'start other thing',
-command => \&start,
)->pack;
my $text = $mw->Text()->pack;
MainLoop;
sub start {
my $script_path = 'this_other_thing.pl';
if (not my $read = do $script_path) {
warn "couldn't parse $script_path: $#" if $#;
warn "couldn't do $script_path: $!" unless defined $read;
warn "couldn't run $script_path" unless $read;
}
}
this_other_thing.pl
#!/usr/bin/env perl
use strict;
use warnings;
use utf8;
print "Hello World!\n";
How can I redirect the STDOUT and STDIN (for interactive scripts that need input) to the text box using the 'do' method? Is that even possible?
If I can't use the 'do' method, what method can redirect the STDIN and STDOUT, as well as enable passing the hash in and using the same version of perl?
Edit: I posted this same question at Perlmonks, at the link in the first comment. So far, the best response seems to use modules and have the child script just be a wrapper for the module. Other possible solutions are: ICP::Run(3) and ICP in general, Capture::Tiny and associated modules, and Tk::Filehandle. A solution was presented that redirects the output and error streams, but seems to not affect the input stream. It's also a bit kludgy and not recommended.
Edit 2: I'm posting this here because I can't answer my own question yet.
Thanks for your suggestions and advice. I went with a suggestion on Perlmonks. The suggestion was to turn the child scripts into modules, and use wrapper scripts around them for normal use. I would then simply be able to use the modules, and all the code is in one spot. This also ensures that I am not using different perls, I can route the output from the module anywhere I want, and passing that hash in is now very easy.
To have both STDIN & STDOUT of a subprocess redirected, you should read the "Bidirectional Communication with Another Process" section of the perlipc man page: http://search.cpan.org/~rjbs/perl-5.18.1/pod/perlipc.pod#Bidirectional_Communication_with_Another_Process
Using the same version of perl works by finding out the name of your perl interpreter, and calling it explicitly. $^X is probably what you want. It may or may not work on different operating systems.
Passing a hash into a subprocess does not work easily. You can print the contents of the hash into a file, and have the subprocess read & parse it. You might get away without using a file, by using the STDIN channel between the two processes, or you could open a separate pipe() for this purpose. Anyway, printing & parsing the data back cannot be avoided when using subprocesses, because the two processes use two perl interpreters, each having its own memory space, and not being able to see each other's variables.
You might avoid using a subprocess, by using fork() + eval() + require(). In that case, no separate perl interpreter will be involved, the forked interpreter will inherit the whole memory of your program with all variables, open file descriptors, sockets, etc. in it, including the hash to be passed. However, I don't see from where your second perl script could get its hash when started from CLI.
I have a perl script the creates a report based on an xml definition. Currently these definitions all exist as .xml files.
So I have the script run-report.pl, which can take a path to a definition file and create the report.
Now I want to create run-reports-from-db.pl, which will generate the report definition based on same database entries. I don't want to create temp files to pass to run-report.pl, I would just like to pass in the definition somehow.
So instead of saying:
run-report.pl -def=./path/to/def.xml
I want to be able to say:
run-report.pl --stream
And have the report definition available in <STDIN>
I am sure there is pretty trivial way to do this???
If I understand your question correctly, all you need is one | (pipe).
./generate-xml-from-db.pl | ./run-report.pl --stream
Anything the first process in the pipeline prints to stdout will appear in the second process's stdin.
As long as you read from STDIN, you have it available. Notice what happens with you take the code below name it something like echo.pl run it at the command line and paste reams of text.
#!/usr/bin/perl -w
use 5.010;
use strict;
use warnings;
while ( <> ) {
say;
}
<> is the Perl shorthand for "read from STDIN".
As long as the method you're using to launch the process has a way to get a hold of the standard input and outputs, you can just write it to that handle. You have to use the ways that are available to you. In Java, for example, you'd have to get the input stream of the process, in a batch command you have to pipe it. At a GUI terminal you can cut and paste.
I'd like a Perl script that I'm writing to display a help message if it receives no input.
How can I tell if nothing is coming in on stdin?
if (#ARGV == 0 && -t STDIN && -t STDERR) {
print STDERR "$0: WARNING: reading input from keyboard, type ^D for EOF, ^C to intr.\n";
}
$#ARGV contains the number of arguments.
http://www.devdaily.com/perl/perl-command-line-arguments-read-args
You might also find this perldoc FAQ useful for checking whether there is any input from the keyboard:
http://perldoc.perl.org/perlfaq8.html#How-do-I-check-whether-input-is-ready-on-the-keyboard%3f
If you are talking about input from STDIN, you can check if the variable is equal to the empty string (after removing the CR/LF). For example:
my $myInput = <STDIN>;
chomp($myInput);
if ($myInput eq "")
{
print "Error! You didn't submit any data!\n";
}
However, as #thnee says, if you are checking for the arguments passed in via command line, you should use $#ARGV.
For example:
if ($#ARGV == -1)
{
print "Error! No input arguments entered!\n";
exit(-1);
}
References:
http://perldoc.perl.org/functions/chomp.html
http://perldoc.perl.org/perlvar.html
It's possible to check if something has come in on STDIN (using a nonblocking read, select or ioctl FIONREAD), but it's impossible to check if something is coming in on stdin, since it hasn't happened yet.
Impossibility aside, you're asking to break convention. For example, take cat, perl, sort, etc, etc. If you provide no arguments, they'll happily wait on STDIN until you provide what they need.
The user knows to use man tool or tool --help to get info.