Heredoc for Java from bash command line - java

As a JAVA teaching assistant, I get stuck with grading a lot of student's labs. A lot of these labs use a Scanner to get input from a user. Instead of repeated bashing numbers into the keyboard, is there a way I can utilize a heredoc to run all of the labs with the same input parameters without changing the student's code? What I have so far (which works for except the heredoc-esque code):
#!/bin/bash
for i in unzip/*; do
echo $i
javac $i/lab0/AddThree.java
cd $i/lab0
java AddThree <<EOF
2
3
4
EOF
cd ../../..
done
The code I'm trying to grade adds three integers that are provided by the user. unzip is the directory where each student has a folder (i.e. file structure is ./unzip/student/lab0/sourcecode.java)
Java gives:
unzip/student
Hello out there
I will add three numbers for you
Enter three whole numbers on a line :
Exception in thread "main" java.util.InputMismatchException
at java.util.Scanner.throwFor(Scanner.java:909)
at java.util.Scanner.next(Scanner.java:1530)
at java.util.Scanner.nextInt(Scanner.java:2160)
at java.util.Scanner.nextInt(Scanner.java:2119)
at AddThree.main(AddThree.java:10)
./lab0test: line 9: 2: command not found
./lab0test: line 10: 3: command not found
./lab0test: line 11: 4: command not found
./lab0test: line 12: EOF: command not found

Your heredoc looks good except it will send the spaces at the start of each line. To get rid of those, you can either use -EOF and start each line of the heredoc with Tab characters, which will get stripped:
cd $i/lab0
java AddThree <<-EOF
TabTab2
TabTab3
TabTab4
TabTabEOF
cd ../../..
Or unindent the heredoc contents. It's ugly, but it'll work.
cd $i/lab0
java AddThree <<EOF
2
3
4
EOF
cd ../../..
Alternatively, if the input is short enough you could do it inline:
java AddThree <<< $'2\n3\n4'
(Using $'...' tells the shell to interpret \n escape sequences.)

Related

Get specific java version with powershell

I have some issues with getting the java version out as a string.
In a batch script I have done it like this:
for /f tokens^=2-5^ delims^=.-_^" %%j in ('%EXTRACTPATH%\Java\jdk_extract\bin\java -fullversion 2^>^&1') do set "JAVAVER=%%j.%%k.%%l_%%m"
The output is: 1.8.0_121
Now I want to do this for PowerShell, but my output is: 1.8.0_12, I miss one "1" in the end Now I have tried it with trim and split but nothing gives me the right output can someone help me out?
This is what I've got so var with PowerShell
$javaVersion = (& $extractPath\Java\jdk_extract\bin\java.exe -fullversion 2>&1)
$javaVersion = "$javaVersion".Trim("java full version """).TrimEnd("-b13")
The full output is: java full version "1.8.0_121-b13"
TrimEnd() works a little different, than you might expect:
'1.8.0_191-b12'.TrimEnd('-b12')
results in: 1.8.0_19 and so does:
'1.8.0_191-b12'.TrimEnd('1-b2')
The reason is, that TrimEnd() removes a trailing set of characters, not a substring. So .TrimEnd('-b12') means: remove all occurrences of any character of the set '-b12' from the end of the string. And that includes the last '1' before the '-'.
A better solution in your case would be -replace:
'java full version "1.8.0_191-b12"' -replace 'java full version "(.+)-b\d+"','$1'
Use a regular expression for matching and extracting the version number:
$javaVersion = if (& java -fullversion 2>&1) -match '\d+\.\d+\.\d+_\d+') {
$matches[0]
}
or
$javaVersion = (& java -fullversion 2>&1 | Select-String '\d+\.\d+\.\d+_\d+').Matches[0].Groups[0].Value

shell script error : [: : integer expression expected

i am trying to trigger an email alert based on the java script output but i am getting an error like below in the shell script,
script.sh: line 22: [: : integer expression expected
Below is my shell script format,
out="$(java -jar /waitrose/scripts/OF/BOBIErrorAutomation/BOBIAutomation.jar
2>&1)"
if [ "$out" -gt 0 ]
then
mail -s "script did not completed successfully" $mailid_list
exit 0
fi
Below is the sample error returned by the java program :
The error was: com.ibm.db2.jcc.c.a.<init>(a.java:174) 174
com.ibm.db2.jcc.c.b.a(b.java:1745) 1745
com.ibm.db2.jcc.b.p.<init>(p.java:934) 934
Can anyone tell me how to capture the output from the java program and trigger the mail in shell ?
are you not comparing the output of your java program which in the case where it crashes, most likely going to be a string of some sort, against (-gt greater than) an integer? the comparator expects a whole number, not a crash message from java.
EDIT: ill elaborate, perhaps it would be better to test if $out is an integer first, if your jar only outputs integers if it runs correctly:
if ! [[ "$out" =~ ^[0-9]+$ ]]
then use this to trigger your mail, and else to normal functionality.

ksh command subsitution with quotes into array

I have a Java class with the following output:
"Roses are red" "Violets are blue" "Daisies are white"
I am trying to create a KornShell (ksh) script that executes this Java class, stores the result into an array, and then outputs
Roses are red
Violets are blue
Daises are white
This is my first attempt at the script:
1 #!/bin/ksh
2
3 set -A colors $(java Colors)
4
5 for i in "${colors[#]}"
6 do
7 echo "$i"
8 done
However, the output looks like this:
"Roses
are
Red"
"Violets
are
blue"
"Daisies
are
white"
When I throw:
echo set -A colors $(java Colors)
into the script to see what is being called, it returns:
set -A colors "Roses are Red" "Violets are blue" "Daisies are white"
If I replace that exact output with line 3 from above, I get the desired output:
Roses are red
Violets are blue
Daises are white
Why does the command substitution throw the whole thing off?
Below is the Java class if that helps:
public class Colors {
public static void main(String[] args) {
System.out.println("\"Roses are Red\" \"Violets are blue\" \"Daisies are white\"");
}
}
So I ended up making it work by throwing an 'eval' in front of the set command. It looked like this:
1 #!/bin/ksh
2
3 eval set -A colors $(java Colors)
4
5 for i in "${colors[#]}"
6 do
7 echo "$i"
8 done
I'm not sure why that worked exactly, but it did.
You may use quotes on $( ) :
set -A colors "$(java Colors)"
to avoid word splitting
pass the output of your java command as arguments to another shell script.
Then it will give $1=>"Roses are red",$2=>"Violets are blue", and so on.
you can get hold of all the input arguments using $#
This sort of thing is distressingly hard to do. This seems to work:
$ cat roses
echo '"Roses are red" "Violets are blue" "Daisies are white"'
$ IFS='
> '
$ set -A colors $(eval printf '%s\\n' $(./roses))
$ printf "%s\n" "${colors[#]}"
Roses are red
Violets are blue
Daisies are white
$
The script ./roses does the same job as your Java class. The variable IFS is the inter-field separator string; it is set to a newline (only). The set line creates an array colors. The value is what you get from executing and capturing eval printf '%s\\n' $(./roses). The second printf statement prints the elements of the array one per line.
Tested with ksh on Mac OS X 10.8.4.
An equivalent in bash is:
$ IFS='
> '
$ colors=($(eval printf '%s\\n' $(./roses)))
$ printf "%s\n" "${colors[#]}"
Roses are red
Violets are blue
Daisies are white
$
Depending a bit on the version of bash, there are probably other ways to do it too.
You should save and restore the value of $IFS before trampling it.
$ old_ifs="$IFS"
$ IFS='
> '
$ ...use the modified value...
$ IFS="$old_ifs"
$

hprof profiler output doesn't include line numbers regardless of `lineno` value

I'm running
java -cp some:jars:out \
-agentlib:hprof=cpu=times,format=a,file=java.hprof.txt,lineno=y,doe=y com.foo.Benchmark \
< /dev/null
and in the output I get stack frames without line numbers
THREAD START (obj=50000150, id = 200002, name="HPROF gc_finish watcher", group="system")
THREAD START (obj=50000151, id = 200001, name="main", group="main")
THREAD START (obj=50000281, id = 200003, name="Thread-1", group="main")
THREAD END (id = 200003)
THREAD END (id = 200001)
THREAD START (obj=500002a5, id = 200004, name="DestroyJavaVM", group="main")
THREAD END (id = 200004)
TRACE 307081:
com.foo.Benchmark.methodName(Benchmark.java:Unknown line)
com.foo.Benchmark.anotherMethodName(Benchmark.java:Unknown line)
...
If I change lineno=y to lineno=n I still get Unknown line.
I compiled the classes with -g. My javac looks like
javac -g -Xlint -encoding UTF-8 -source 1.5 -d out -classpath ... src/main/com/foo/*.java
I checked the .class files to make sure they have line numbers:
javap -classpath out -c -l com.foo.Benchmark
shows plenty of things like
LineNumberTable:
line 1077: 0
line 1078: 8
line 1079: 14
line 1080: 21
line 1082: 23
line 1083: 31
line 1084: 43
Am I using some flag combination that prevents line number output?
I faced exactly the same problem, but compiling the source with -g helped. After compiling with -g, I see the line numbers like this (which I don't see otherwise, without -g option) -
LineNumberTable:
line 16: 0
line 17: 8
line 18: 12
line 19: 20
line 18: 29
line 21: 35
Now, if I run this -
java -cp "./build/classes" -agentlib:hprof=heap=sites,depth=20 org.sample.welcome.Main a b c
I do get the line numbers for the user-defined classes. Even though I am not sure what's going wrong in your case, these are my observations -
Using javac without -g: If I have -lineno (default y) set to y, I still don't see the line numbers for most of the classes except for the user-defined classes (Main in the above case). If I've set -lineno to n, then I won't see line numbers for any of the classes anyway.
Using javac with -g: If I have -lineno set to y, I can see the line numbers for all the classes (not sure what's going wrong in your case).
The only documentation I could find for HPROF doesn't say anything beyond this. I think one option would be to try with fewer optional arguments and see the results.
Note: I'm using JDK 1.6 in the above example

javap -l option cannot display line number info

The javap command has several options, one of them is -l, which can print line number and local variable tables. Suppose a java program has been compiled successfully and there is the file "Main.class", so running javap -l Main can produce something like:
public static void main(java.lang.String[]);
LineNumberTable:
line 100: 0
line 101: 27
line 275: 54
LocalVariableTable:
Start Length Slot Name Signature
0 55 0 args [Ljava/lang/String;
However, I'm using this javap -l xxx command on the class files of one java program, but the area of line number and local variable table is empty (which shouldn't be). The javap command and other options such as -s, -verbose works fine, but only the line info area corresponding to the -l option is empty.
Has anyone ever encountered such weird case?
Use -g to compile your code, otherwise the line numbers are not kept (akin to the stack trace displaying "compiled code" instead of the line number)

Categories

Resources