首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >用嵌套引号调用ProcessBuilder终端函数?

用嵌套引号调用ProcessBuilder终端函数?
EN

Stack Overflow用户
提问于 2022-09-17 19:50:53
回答 1查看 40关注 0票数 0

我在Linux上,正在编写一个子程序来更改mp3文件的ID标记。

此命令工作:kid3-cli -c "tag 1" -c "set Title "TITLE"" -c "set Artist "ARTIST"" FILENAME.EXT

我尝试在ProcessBuilder中尝试这样的方法:

代码语言:javascript
复制
new ProcessBuilder(Arrays.asList("kid3-cli", "-c", "\"tag", "1\"", "-c", "\"set", "Title", "\"" + title + "\"\"",
                                    "-c", "\"set", "Artist", "\"" + artist + "\"\"", path.toString()))

我还想把引号作为一个参数来处理:

代码语言:javascript
复制
new ProcessBuilder(Arrays.asList("kid3-cli", "-c", "\"tag 1\"", "-c", "\"set Title \"" + title + "\"\"",
                                    "-c", "\"set Artist \"" + artist + "\"\"", path.toString())

它是否成功,可通过以下方式加以验证:

代码语言:javascript
复制
kid3-cli -c "get" SONG.EXT

当我运行该程序时(使用一些有用的调试语句,我得到:

代码语言:javascript
复制
INFO: COMMAND: kid3-cli -c "tag 1" -c "set Title "Unfinished Cathedral"" -c "set Artist "DAN TERMINUS"" /home/sarah/Music/Indexing/Temp/DAN TERMINUS - Unfinished Cathedral.mp3

标签的内容如下:

代码语言:javascript
复制
(base) sarah@MidnightStarSign:~/Music/Indexing/Temp$ kid3-cli -c "get" DAN\ TERMINUS\ -\ Unfinished\ Cathedral.mp3 
File: MPEG 1 Layer 3 128 kbps 44100 Hz Joint Stereo 4:38
  Name: DAN TERMINUS - Unfinished Cathedral.mp3
Tag 2: ID3v2.3.0
  Title                   
  Artist                  
  Album                   
  Comment                 Visit http://dan-terminus.bandcamp.com
  Date                    2014
  Track Number            9
  Album Artist            DAN TERMINUS
  Picture: Cover (front)  cover

我相当肯定,我在给流程构建器的条目数量方面做错了什么,但我不确定。我怎么才能让它表现得正常呢?

编辑0:

奇怪的是。这也会失败(尽管它在查询命令时具有完全相同的输出,如果在bash上运行,则会更改标记):

代码语言:javascript
复制
new ProcessBuilder(Arrays.asList("bash", "-c", "\"kid3-cli -c \"tag 1\" -c \"set Title \"" + title + "\"\" -c \"set Artist \""
                                + artist + "\"\"" + path.toString() + "\"");

虽然它会导致正确的字符串:INFO: COMMAND: bash -c "kid3-cli -c "tag 1" -c "set Title "Unfinished Cathedral"" -c "set Artist "DAN TERMINUS""/home/sarah/Music/Indexing/Temp/DAN TERMINUS - Unfinished Cathedral.mp3"

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-09-18 06:19:54

这里有两个问题:

  • 你的命令不是按照你想的去做。
  • 双引号适用于shell(如bash),而不是程序中的直接执行。

首先,让我们看一下命令的命令行版本:

此命令工作:kid3-cli -c "tag 1" -c "set Title "TITLE"" -c "set Artist "ARTIST"" FILENAME.EXT

是的,它“有效”,但并不是因为你认为的原因。引号内的嵌套引号不只是神奇地起作用。对于任何解析器来说,几乎不可能知道哪些引号字符是参数的结尾,哪些字符是参数的一部分。

你真正要做的是:

代码语言:javascript
复制
kid3-cli -c "tag 1" -c "set Title "TITLE"" -c "set Artist "ARTIST"" FILENAME.EXT
╰──┬───╯ ╰┬╯ ╰─┬─╯ ╰┬╯  ╰──────┬── ────╯   ╰┬╯ ╰────────┬─ ─────╯   ╰────┬─────╯
  arg0  arg1  arg2 arg3       arg4        arg5        arg6             arg7
(program
  path)

正如您所看到的,每个引用的参数都是一个参数。这意味着您希望将每个引用的参数作为单个参数传递给ProcessBuilder,而不使用这些引号。双引号仅在shell (如bash)中是特殊的,它们指示带空格的值不应被shell拆分为多个参数。

但还有更多。当你这样做时:

代码语言:javascript
复制
"set Title "TITLE""

您没有在参数中指定带有双引号的参数。所有这些双引号字符都由shell解释,因此它们都不会传递给kid3-cli程序。

实际上正在发生的是将一个引用的字符串、一个未引用的标题、然后一个空的引号串连接到一个命令行参数中。这些都是完全相同的:

代码语言:javascript
复制
"set Title "TITLE""
"set Title "TITLE
'set Title 'TITLE
set\ Title\ TITLE

所以,那些双引号根本没有传递给程序。

ProcessBuilder不需要任何引号,因为它不是shell;而是直接执行带有给定参数的程序。您已经告诉ProcessBuilder什么构成了程序的单个参数,只需将每个这样的参数作为单独的字符串参数值传递即可。

(附带说明:Arrays.asList是不必要的。ProcessBuilder有直接接受字符串参数的构造函数。

代码语言:javascript
复制
new ProcessBuilder("kid3-cli",
    "-c", "tag 1",
    "-c", "set Title \"" + title + "\"",
    "-c", "set Artist \"" + artist + "\"",
    path.toString())

kid3手册页似乎更喜欢使用单引号字符作为kid3命令的参数,这可能会使事情变得更容易阅读,也更容易混淆:

代码语言:javascript
复制
new ProcessBuilder("kid3-cli",
    "-c", "tag 1",
    "-c", "set Title '" + title + "'",
    "-c", "set Artist '" + artist + "'",
    path.toString())
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73758056

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档