【问题标题】:shell string bad substitutionshell 字符串错误替换
【发布时间】:2012-10-11 03:36:24
【问题描述】:

我是 shell 编程的新手。我打算在提取 zip 文件后获取目录名称。它的打印语句是

$test.sh helloworld.zip
helloworld

我们来看看test.sh:

#! /bin/sh
length=echo `expr index "$1" .zip`
a=$1    
echo $(a:0:length}

但是我从编译器中得到了错误的替换错误。

当我提到“shell”时。我只是在谈论 shell,因为我不知道 bash 或其他之间的区别。我只是使用 Ubuntu 10.04 并使用终端。 (我正在使用 bash。)

【问题讨论】:

  • 你对脚本的参数是什么,即 $1 的值?请将此信息编辑到您上面的消息中,而不是作为对我的评论的回复。尝试在 dbl-quotes 中包含对 $1 的所有引用,即echo "$1" 等。祝你好运!
  • 你用${a:0} 表达了什么?
  • 尝试将第一行更改为#!/bin/bash。祝你好运。
  • 哇,添加#! /bin/bash 有效。为什么?使用 #! 有什么区别? /bin/bash 和 #! /bin/sh
  • 它们是实现不同功能的不同外壳。即使/bin/sh 是 bash,它也会像使用 --posix 一样执行,这会禁用一些 bash 功能。

标签: string shell substitution


【解决方案1】:

如果您的 shell 是 bash 的最新版本,那么 parameter expansion 表示法应该可以工作。

在许多其他 shell 中,它不起作用,bad substitution 错误是 shell 说“您要求进行参数替换,但它对我没有意义”的方式。


另外,给定脚本:

#! /bin/sh
length=echo `expr index "$1" .zip`
a=$1    
echo $(a:0:length}

第二行导出变量length,其值为echo,用于运行expr index "$1" .zip 生成的命令。它不分配给length。那应该只是:

length=$(expr index "${1:?}" .zip)

如果$1 未设置(如果调用脚本时不带参数),${1:?} 表示法会生成错误。

最后一行应该是:

echo ${a:0:$length}

请注意,如果$1 持有filename.zip,则expr index $1 .zip 的输出为2,因为字母i 出现在filename.zip 的索引2 处。如果打算获取不带 .zip 扩展名的文件的基本名称,那么经典的方法是:

base=$(basename $1 .zip)

更现代的方式是:

base=${1%.zip}

有区别;如果名称为/path/to/filename.zip,则经典输出为filename,现代输出为/path/to/filename。您可以通过以下方式获得经典输出:

base=${1%.zip}
base=${base##*/}

或者,在经典版本中,您可以通过以下方式获取路径:

base=$(dirname $1)/$(basename $1 .zip)`.)

如果文件名可以包含空格,则需要考虑使用双引号,尤其是在basenamedirname 的调用中。

【讨论】:

  • 什么是“足够新的版本”?我正在使用 bash 4.2.37,我遇到了这个问题。
  • @Simon:它适用于 Bash 3.2.51(随 Mac OS X 10.9.2 Mavericks 提供)。它也适用于 Bash 4.2.25(随 Ubuntu 12.04 提供)。例如:AZ=abcdefghijklmnopqrstuvwxyz; echo ${AZ:10:10} 在两个系统上产生 klmnopqrst。此外,无论是 Bash 以bash 还是sh 运行,它都可以正常工作。因此,您需要按照我刚刚给出的示例详细说明您正在做什么。请注意,两个值都必须是数字。您可以写:length=10echo ${AZ:10:$length},但第二个 $ 在该符号中至关重要。
  • 感谢您的快速答复。实际上AZ=abcdefghijklmnopqrstuvwxyz; echo ${AZ:10:10} 为我产生了Bad substitution(Bash 4.2.37 - Debian 7.4)。我想我必须深入挖掘。
  • @Simon:现在这是一种奇怪的情况。我想您将需要追踪 4.2.37 与 4.2.25 中的内容或其他内容(不能保证您的“.25”与“我的”相同)。 Bash 4.3 由 Gnu 于 2014 年 2 月 26 日发布(4.2 于 2011 年 2 月 13 日)。也许尝试构建它?否则,您可能会遇到回归错误。 (我刚刚在 Mac OS X 10.9.2 上构建了 Bash 4.3,同时添加了这条评论 - 完成下载后花了几分钟时间 - AZ-test 在它上面运行得很干净。)
  • @Simon — 五年后我突然想到你可能(曾经)使用dash 而不是bash
【解决方案2】:

尝试使用 bash 运行它。

bash test.sh helloworld.zip

-同样-

“尝试将第一行更改为 #!/bin/bash”作为评论回答 – @shellter

【讨论】:

  • 我使用的是sh test.sh 并更新了bash test.sh。谢谢
【解决方案3】:

bash 中尝试:

echo $1
len=$(wc -c <<< "$1")
a="${1}.zip"
echo ${a:0:$len}

调整它以满足您的需求。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-07
    • 2014-11-24
    • 2013-05-26
    • 1970-01-01
    相关资源
    最近更新 更多