I'm working on automating an interactive command line Java program in bash to validate that the program produces proper output for the input (basically poor-man's unit testing in bash).
For example, if I have a java program that asks the user to enter their full name, and then outputs only their first name, it should look something like this:
Enter your name: John Doe
John
Where "John Doe" was typed in by the user.
A simple bash command to run this might look like this:
OUTPUT=`echo "John Doe" | java NameReader`
or
OUTPUT=`java NameReader <<< "John Doe"`
The trouble with both of these is that $OUTPUT now contains the following:
Enter your name: John
Because the text that was sent to stdin (and its newline accompanying) isn't reproduced in the output of the program the way we would see it in the console.
Ideally, $OUTPUT would contain this:
Enter your name: John Doe
John
But I could live with this:
Enter your name:
John
(The input is omitted entirely, but the output is on a new line, as expected)
Is there a way in bash (without altering the underlying java program) to get the text that is being piped to stdin to also pipe to stdout at the "time" it's read by the java program, so the full interactive session is captured?
(One more note: Some searching indicated that the spawn/expect commands might be helpful, but the system this will run on does not appear to have them available)
To store the output of a command in a variable, you can use the shell command substitution feature in the forms below: variable_name=$(command) variable_name=$(command [option ...] arg1 arg2 ...) OR variable_name='command' variable_name='command [option ...]
Scripts may be forced to run in interactive mode with the -i option or with a #!/bin/bash -i header.
You can use the script
command
script -q -c "java NameReader" log.txt
This will record the input and ouput of the java NameReader
command in the log.txt
file.
If your java program is like this:
import java.util.Scanner;
class A {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println(sc.next());
}
}
then you could build a bash script that would parse an input of the form
Enter your name: John
John Doe
to transform it into
Enter your name: John Doe
John
Here is one possible bash script:
#!/bin/bash
arg1Outpt=`eval "$1"`
javaOut=`echo "$arg1Outpt" | eval "$2"`
#prints Enter your name: John\nJohn Doe
echo "${javaOut}"$'\n'"${arg1Outpt}" |
sed 'N; s/\(Enter your name: \)\(.*\)\(\n\)\(.*\)/\1\4\3\2/'
#and this is a multiline sed(man sed) that transforms your
#input into what you want :)
use it like this:
bash pipeCheat.bash 'echo "john doe"' 'java A'
where pipeCheat.bash is the name of the file where you saved the script above.
If you have questions don't hesitate to ask.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With