2009-04-13 81 views
28

在我的Java命令行參數中,空格後的任何字符都被忽略。例如,Java命令行參數中的空間

java test.AskGetCampaignByName "Dummy books" 

我只將第一個參數(args [0])作爲「Dummy」。單引號也沒有幫助。 有沒有人知道任何解決方法/修復?可能是因爲我的終端設置? 我的$ TERM是xterm,$ LANG是「en_IN」。

回答

53

參數由shell處理(我假設你在linux下使用bash?),所以任何終端設置都不應該影響這個。既然你已經引用了它應該工作的論點。我能想到的唯一可能的解釋是,如果你的java命令是一個包裝腳本,並在傳遞給真實程序時混淆了參數的轉義。這很容易做到,或者可能難以正確執行。

一個正確的包裝腳本應該將其所有參數作爲${1+"[email protected]"}傳遞,任何其他版本最有可能是一個關於能夠正確處理嵌入空間的錯誤。這種做法並不少見,但是任何發生的$2或類似事件都很麻煩,必須寫爲"$2"(或可能爲${2+"$2"})才能正確處理嵌入的空間,這是非常有罪的。

不是那麼直觀的語法${1+"[email protected]"}的原因是原來的$*加入所有參數作爲"$1 $2 $3 ..."這對嵌入式空間不起作用。然後"[email protected]"被引入(正確地)擴展到"$1" "$2" "$3" ...的所有參數,如果沒有給出參數,它應該擴展到無。不幸的是一些UNIX供應商搞砸並提出"[email protected]"擴大到""即使在沒有參數的情況下,並解決這個聰明的(但不是那麼可讀)寫${1+"[email protected]"}的黑客被髮明,使得"[email protected]"僅在參數$1設置擴大(即避免在沒有參數的情況下進行擴展)。

如果我的包裝的假設是錯誤的,你可以嘗試用strace的

strace -o outfile -f -ff -F java test.AskGetCampaignByName "Dummy books" 

調試,並找出參數傳遞給execve的。從運行「strace /bin/echo '1 2' 3

execve("/bin/echo", ["/bin/echo", "1 2", "3"], [/* 93 vars */]) = 0 
brk(0)         = 0x2400000 
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f420075b000 
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f420075a000 
access("/etc/ld.so.preload", R_OK)  = -1 ENOENT (No such file or directory) 
open("/usr/lib64/alliance/lib/tls/x86_64/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory) 
stat("/usr/lib64/alliance/lib/tls/x86_64", 0x7fff08757cd0) = -1 ENOENT (No such file or directory) 
open("/usr/lib64/alliance/lib/tls/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory) 
... 
+1

非常感謝! 就是這樣。我們通過ant build生成一個可執行文件來設置類路徑等。我們在腳本中使用了「java @」。用你的$ {1 +「@」}來代替問題。對不起,在我的示例中直接使用java會導致誤導。我認爲它意味着相同 – ashweta 2009-04-13 13:45:39

0

如果你的程序需要的不止是位置參數(=當命令行用法很重要),你應該考慮選項和開關。 Apache Commons對此有很好的library

0

聽起來就像您正在使用的操作系統發行版,其中可用於用戶的java命令是一個包裝器,它可以找到正確的JVM「某處」並相應地調用它。

如果是這樣,那麼在調用實際的java可執行文件時,它很可能不會正確地轉義參數。

你使用什麼樣的分佈?

+0

在我的Windows機器'的 「Hello World」, 「Hello World」 的 「世界你好」'傳遞的命令行參數將有所回升爲ARGS [0(/ 1)(/2)] ==「hello world」,在Linux上這根本不起作用(我不記得它做了什麼*,因爲我並不太在意)。但我很樂意看到任何解決方案。感謝您的問題。 @ThorbjørnRavn Andersen,請詳細說明。我如何改變JVM的調用方式? – 2009-04-13 10:43:29

-3

這個問題的例子是有點老了,但你爲什麼不只是重新組裝在Java程序中的ARGS?

StringBuilder allArgs = new StringBuilder(); 
for (int i=0; i < args.length; i++) 
{ 
    //System.out.println("arg"+i+": "+args[i]); 
    allArgs.append(args[i]+" "); 
} 
//Parse out the args the way you wish using allArgs 
+0

由於`java test.AskGetCampaignByName「虛擬書籍」`Dummy`和`books`之間有多個空格將會失敗(Stack Overflow輸出爲單個空間,所以在這裏你看不到它。 ..) – leemes 2012-07-16 00:23:49

+0

因爲`java`應該從shell中正確地獲取命令行參數。 – Olathe 2013-03-03 14:50:27

1

你一定要逃出這樣的空間:

normal String: "Hello World!" 
escaped String: "Hello" "World!" 

爲我工作。

我的環境:

23:39:19 [email protected]:/Users/Zarathustra~$bash -version 
GNU bash, version 3.2.48(1)-release (x86_64-apple-darwin11) 
Copyright (C) 2007 Free Software Foundation, Inc.