digitalmars.D.learn - Piping from terminal into D program
- eXodiquas (23/23) Sep 04 2021 Hello everyone,
- Brian Tiffin (23/47) Sep 04 2021 There are two things happening here. Command line arguments and
- WebFreak001 (36/60) Sep 04 2021 to extend on Brian Tiffin's reply, you can read from the standard
- eXodiquas (4/10) Sep 04 2021 Brian Tiffin's and your reply really cleared things up for me.
- =?UTF-8?B?0JLQuNGC0LDQu9C40Lkg0KTQsNC0?= =?UTF-8?B?0LXQtdCy?= (9/15) Sep 05 2021 Of course, pipe ( | ./nounscramble ) is not args ( ./nounscramble
Hello everyone,
I created a small little D program that reads in a string from 
the command line and shuffles the letters of the nouns a bit 
around. This is pretty straight forward, but what I see now 
happening is a bit strange, at least for me.
I am reading the args out of the main function arguments.
```d
void main(string[] args) {
   args.writeln();
}
```
this works fine whenever I call the program like `./nounscramble 
"Hello, my name is Earl!"` the string shows up in `args[1]`. But 
when I call `echo "Hello, my name is Earl!" | ./nounscramble` it 
does not show up in the args array, the only thing showing up is 
the name of the executable (which is expected).
My question is now, can someone explain what I am doing wrong? 
Maybe I misunderstood the pipe in Linux systems and it is obvious 
for someone who knows how this works exactly, or maybe D works 
differently with pipes and I havn't found the correct 
documentation.
Thanks in advance. :)
eXodiquas
 Sep 04 2021
On Saturday, 4 September 2021 at 15:41:51 UTC, eXodiquas wrote:
 Hello everyone,
 I created a small little D program that reads in a string from 
 the command line and shuffles the letters of the nouns a bit 
 around. This is pretty straight forward, but what I see now 
 happening is a bit strange, at least for me.
 I am reading the args out of the main function arguments.
 ```d
 void main(string[] args) {
   args.writeln();
 }
 ```
 this works fine whenever I call the program like 
 `./nounscramble "Hello, my name is Earl!"` the string shows up 
 in `args[1]`. But when I call `echo "Hello, my name is Earl!" | 
 ./nounscramble` it does not show up in the args array, the only 
 thing showing up is the name of the executable (which is 
 expected).
 My question is now, can someone explain what I am doing wrong? 
 Maybe I misunderstood the pipe in Linux systems and it is 
 obvious for someone who knows how this works exactly, or maybe 
 D works differently with pipes and I havn't found the correct 
 documentation.
 Thanks in advance. :)
 eXodiquas
There are two things happening here.  Command line arguments and 
stdin, standard in.
When part of an actual command line, parameters are expanded as 
command line arguments, passed to the `main` function.  When 
`echo`ed, the arguments are passed to the `echo` command, which 
then displays those arguments on stdout, standard out.  A pipe is 
connecting the stdout of the left hand side, and streaming that 
data to the stdin of the right hand side, after the pipe symbol.  
These are not command line arguments, but data on the 
stdin/stdout channels (file descriptors to be more exact with the 
jargon).
You could write is as `echo thing | ./nounscramble commandarg`.
`echo` will display *thing*. Your program with get `commandarg` 
in the array passed to `main`, but the stdout data displayed by 
`echo` is never read, and just ends up in a pipeline bitbucket at 
the end of processing.
Most shells, like `bash` allow a different kind of parameter 
replacement, command arg expansion.  Use like `./nounstatement 
$(echo this that)`, and the shell will manipulate things to 
replace the stdout from the `echo` into word expanded arguments 
placed in the atring array used by `main`.
Cheers
 Sep 04 2021
On Saturday, 4 September 2021 at 15:41:51 UTC, eXodiquas wrote:
 Hello everyone,
 I created a small little D program that reads in a string from 
 the command line and shuffles the letters of the nouns a bit 
 around. This is pretty straight forward, but what I see now 
 happening is a bit strange, at least for me.
 I am reading the args out of the main function arguments.
 ```d
 void main(string[] args) {
   args.writeln();
 }
 ```
 this works fine whenever I call the program like 
 `./nounscramble "Hello, my name is Earl!"` the string shows up 
 in `args[1]`. But when I call `echo "Hello, my name is Earl!" | 
 ./nounscramble` it does not show up in the args array, the only 
 thing showing up is the name of the executable (which is 
 expected).
 My question is now, can someone explain what I am doing wrong? 
 Maybe I misunderstood the pipe in Linux systems and it is 
 obvious for someone who knows how this works exactly, or maybe 
 D works differently with pipes and I havn't found the correct 
 documentation.
 Thanks in advance. :)
 eXodiquas
to extend on Brian Tiffin's reply, you can read from the standard 
input stream (the data piped to your program) using std.stdio's 
`stdin`
Example:
```d
import std.stdio;
foreach (line; stdin.byLine)
     writeln("got input line: ", line);
// IMPORTANT: the line buffer is reused (it's a char[], not a 
string), so if you want to store it in a variable outside the 
foreach, use .idup to make it a string (that is not changed when 
leaving the loop)
```
or
```d
import std.stdio;
foreach (chunk; stdin.byChunk(1024))
     writeln("got input chunk: ", cast(char[])chunk);
// same warning as above, don't case to string (that's unsafe and 
wouldn't be allowed in  safe code, but casting to char[] is safe, 
as it explicitly says it can be changed)
```
or
```d
import std.stdio;
ubyte[1024] buffer;
auto part = cast(char[])stdin.rawRead(buffer[]);
writeln("got part: ", part);
// this is the lower level equivalent of the byChunk above, it's 
just doing a single step instead of multiple chunks, so you 
control when it is changed.
// a slice of this buffer (which is what the return value is) 
needs to be .idup'd to be persisted outside the lifetime of the 
`buffer` variable
```
 Sep 04 2021
On Saturday, 4 September 2021 at 18:20:51 UTC, WebFreak001 wrote:On Saturday, 4 September 2021 at 15:41:51 UTC, eXodiquas wrote:Brian Tiffin's and your reply really cleared things up for me. Thank you very much for the detailed answer and your time. Have a nice day. :)[...]to extend on Brian Tiffin's reply, you can read from the standard input stream (the data piped to your program) using std.stdio's `stdin` [...]
 Sep 04 2021
On Saturday, 4 September 2021 at 15:41:51 UTC, eXodiquas wrote:My question is now, can someone explain what I am doing wrong? Maybe I misunderstood the pipe in Linux systems and it is obvious for someone who knows how this works exactly, or maybe D works differently with pipes and I havn't found the correct documentation. eXodiquasOf course, pipe ( | ./nounscramble ) is not args ( ./nounscramble arg1 arg2 ). Pipe `stdin -> ( read buf -> write buf ) -> stdout` Args `main( args ) -> write arg1, arg2 -> stdout` Check the D std.stdio. https://dlang.org/phobos/std_stdio.html Check the shell tool `xargs`. https://en.wikipedia.org/wiki/Xargs
 Sep 05 2021








 
  
  
 
 Brian Tiffin <btiffin gnu.org>
 Brian Tiffin <btiffin gnu.org> 