为什么zsh语法在这个脚本中不起作用?

时间:2014-07-11 08:15:21

标签: shell zsh

我只是想了解这里发生了什么,以便我了解如何更好地解析shell脚本中的字符串。

我知道通常,当您尝试将由空格分隔的一串参数直接传递给命令时,它们将被视为单个字符串参数,因此无法识别:

>check="FileA.txt FileB.txt"
>ls $check
ls: cannot access FileA.txt FileB.txt: No such file or directory

但是,在此脚本中,两个参数分别作为空格分隔的字符串。在这种情况下,两个字符串都被识别为可以传递给不同命令的参数列表:

testscript.sh

while getopts o:p: arguments
do  
    case $arguments in
    o) olist="$OPTARG";;
    p) plist=$OPTARG;;
    esac
done
echo "olist"
ls -l $olist
echo "plist"
ls -l $plist

输出如下:

>testscript.sh -o "fileA.txt fileB.txt" -p "file1.txt file2.txt"
Olist
fileA.txt
fileB.txt
plist
file1.txt
file2.txt

这里有什么不同?为什么空格分隔的字符串突然被识别为列表?

2 个答案:

答案 0 :(得分:2)

您的脚本不以#!行开头,因此未指定解释器。在这种情况下,使用默认值/bin/sh,而不是您的登录shell或您正在启动脚本的shell(当然,除非/bin/sh)。 /bin/sh不是zsh的可能性很大,因为大多数发行版和统一使用似乎都使用shbashdashksh作为zsh默认shell。所有这些都处理参数扩展,如果参数没有引用双引号,则字符串作为列表处理。

如果要使用#!/usr/bin/zsh 作为脚本的解释器,则必须在脚本的第一行指定它:

zsh

修改env所在位置的路径。

您也可以使用#!/usr/bin/env zsh 作为包装器:

zsh

这使您更加独立于$PATH的实际位置,它只需位于{{1}}。

答案 1 :(得分:1)

事实上(使用bash)......

sh$ check="FileA.txt FileB.txt"
sh$ ls $check
ls: cannot access FileA.txt: No such file or directory
ls: cannot access FileB.txt: No such file or directory

当您在没有引号的情况下编写$check时,该变量的内容是替换。内部步调(或在IFS出现时精确)被视为场分隔符。就像你首先期待它一样。

我知道重现行为的唯一方法是将IFS设置为其默认值以外的其他值:

sh$ export IFS="-"
sh$ check="FileA.txt FileB.txt"
sh$ ls $check
ls: cannot access FileA.txt FileB.txt: No such file or directory