【问题标题】:Bash script error: unexpected EOF while looking for matching `''Bash 脚本错误:查找匹配的“”时出现意外的 EOF
【发布时间】:2016-07-09 19:04:39
【问题描述】:

我正在尝试运行此 shell 脚本,但出现错误:

在寻找匹配的 `'' 时出现意外的 EOF

语法错误:文件意外结束

当我将 .asd/' 切换到 .asd/' 时没有错误,但似乎什么也没发生。该脚本的目标是告诉我 /Music 中的哪些音乐文件没有对应的 .asd 文件。脚本是:

#!/bin/bash
files=`mdfind -onlyin ~/Music “kMDItemUserTags==Green” | sed -E -e 's/\.[a-zA-Z1-3]+$/.asd/‘`
for aFile in $files 
do
    if [ ! -e $aFile ]; then
        echo $aFile;
    fi
done

提前感谢您的帮助。

【问题讨论】:

  • 无论您使用什么编辑器编写脚本,都不要使用它。这看起来像一个 MS-Word 文本文件被保存为一个脚本,所有花哨的 UTF-8 大引号而不是 ASCII 纯引号。

标签: bash macos shell


【解决方案1】:

补充Alex Ives's helpful answer

shellcheck.net 对语法检查 shell 脚本的赞誉已经被唱了很多次,这是有道理的:

如果我们将您的脚本粘贴到那里(为了便于阅读,将管道分成 2 行之后),我们会得到(这里省略了附加的附带消息,但在下面进一步列出):

Line 2:
files=`mdfind -onlyin ~/Music “kMDItemUserTags==Green” | 
                              ^-- SC1015: This is a unicode double quote. Delete and retype it.
                                                     ^-- SC1015: This is a unicode double quote. Delete and retype it.

Line 3:
  sed -E -e 's/\.[a-zA-Z1-3]+$/.asd/‘`
                                    ^-- SC1016: This is a unicode single quote. Delete and retype it.

如您所见,shellcheck.net 会发现您的问题并另外提供以下提示:

Line 2:
files=`mdfind -onlyin ~/Music “kMDItemUserTags==Green” | 
      ^-- SC2006: Use $(..) instead of legacy `..`.

Line 6:
    if [ ! -e $aFile ]; then
              ^-- SC2086: Double quote to prevent globbing and word splitting.

Line 7:
        echo $aFile;
             ^-- SC2086: Double quote to prevent globbing and word splitting.

此外,您不应该使用for 枚举文件名,因为这会破坏带有嵌入空格的文件名。

改为:

while IFS= read -r aFile; do
  # work with "$aFile"
done < <(mdfind -onlyin ~/Music ...)

William Pursell 在评论中正确指出 IFS= read -r aFile 失败,文件名带有嵌入的换行符
也就是说,嵌入换行符的文件名很少是现实世界的关注点。相比之下,嵌入 空格 的文件名是,IFS= read -r aFile 处理正确的情况。

【讨论】:

  • while IFS= read -r aFile 将在名称包含嵌入换行符的文件上失败。您实际上只能在 nul 字节上可靠地拆分。例如,while read -d $'\0',但执行不允许在文件名中使用空格的策略更为明智。
【解决方案2】:

看起来你在 mdfind 中有大引号。弯引号的解释方式与直引号不同。因此,虽然用' 替换 解决了文件结尾错误,但您可能没有与“kMDItemUserTags==Green” 匹配任何内容。尝试用"kMDItemUserTags==Green" 替换它,看看是否可行。

单引号的情况是它匹配第一个而不是第二个,所以当你到达结束引号(卷曲)时,它一直认为这是引用字符串的一部分,并一直阅读直到结束文件 (EOF)。

希望有帮助!

【讨论】:

  • 哎呀,n't 确实在上下文中有所不同。
  • 感谢您的快速回答!不幸的是,没有运气-也许脚本有问题(或者我误解了-脚本是为我编写的;我超出了我的知识范围)。当我运行脚本时,使双引号和单引号都变直(并留下反引号)不会产生任何结果。拉直双引号并保留单引号会产生与以前相同的错误,但我假设我不应该这样做。
  • @Farinuts:“拉直”引号绝对是必要的;如果在那之后您没有得到结果,这意味着您的 Spotlight 查询 (mdfind ...) 根本不返回任何结果。我建议你接受这个答案,因为它解决了你最初的问题,如果你有一个关于为什么你的 mdfind 命令不起作用的后续问题,问一个 new 问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-02-14
  • 1970-01-01
  • 2019-01-19
  • 2014-10-09
  • 2023-03-05
  • 2017-07-29
  • 2020-12-18
相关资源
最近更新 更多