String 壳串错误替换

String 壳串错误替换,string,shell,substitution,String,Shell,Substitution,我不熟悉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和终端。(我

我不熟悉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。)

如果您的shell是
bash
的最新版本,那么该符号应该可以使用

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


此外,考虑到脚本:

#! /bin/sh
length=echo `expr index "$1" .zip`
a=$1    
echo $(a:0:length}
第二行为通过运行
expr index“$1”.zip生成的命令导出变量
length
,其值为
echo
。它不分配给
长度
。这应该是:

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)`.)

如果文件名可以包含空格,则需要考虑使用双引号,特别是在调用
basename
dirname
时,请在
bash
中尝试使用双引号:

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

len=$(wc-c尝试用bash运行它

bash test.sh helloworld.zip

-同样地-


“尝试将第一行更改为#!/bin/bash”作为由–@Sheller

回答的评论,脚本的参数是什么,即$1的值?请将此信息编辑到上面的消息中,而不是作为对我评论的答复。尝试在dbl引号中包含对$1的所有引用,即
echo”$1”
,等等。祝你好运!你用
${a:0}体验了什么
?尝试将第一行更改为
!/bin/bash
。祝你好运。哇,添加#!/bin/bash会起作用。为什么?使用#!/bin/bash和#!/bin/sh有什么区别?它们是实现不同功能的不同shell。即使
/bin/sh
是bash,它的执行就像使用了
-posix
一样,这会禁用一些bash功能Thres.什么是“足够新的版本”?我正在使用bash 4.2.37,我面临着这个问题。@Simon:它适用于bash 3.2.51(随Mac OS X 10.9.2 Mavericks提供)。它也适用于bash 4.2.25(随Ubuntu 12.04提供)。例如:
AZ=abcdefghijjklmnopqrstuvxyz;echo${AZ:10}
在两个系统上都产生
klmnopqrst
。此外,无论是Bash作为
Bash
运行还是作为
sh
运行,它都可以正常工作。因此,您需要按照我刚才给出的示例详细说明您正在执行的操作。请注意,这两个值都必须是数字。您可以编写:
length=10
echo${AZ:10:$length}
但是第二个
$
在这个符号中是至关重要的。谢谢你的快速回答。实际上,
AZ=abcdefghijklmnopqrstuvwxyz;echo${AZ:10:10}
对我来说产生了一个
糟糕的替换(Bash 4.2.37-Debian 7.4)。我想我必须更深入地挖掘。@Simon:现在这是一种奇怪的情况。我想你需要追踪4.2.37和4.2.25中的内容,或者是Gnu 2014-02-26(2011-02-13的4.2)发布的东西(不保证你的“.25”与我的相同)。或许可以尝试构建它?否则,你可能会有一个回归错误。(我刚刚在Mac OS X 10.9.2上构建了Bash 4.3,同时添加了这条评论-下载完成后花了几分钟时间-AZ测试在上面运行得很干净。)@Simon-五年后,我意识到你可能(已经)是使用
dash
而不是
bash
。我使用了
sh test.sh
并更新了
bash test.sh
。谢谢