我只是想了解这里发生了什么,以便我了解如何更好地解析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
这里有什么不同?为什么空格分隔的字符串突然被识别为列表?
答案 0 :(得分:2)
您的脚本不以#!
行开头,因此未指定解释器。在这种情况下,使用默认值/bin/sh
,而不是您的登录shell或您正在启动脚本的shell(当然,除非/bin/sh
)。 /bin/sh
不是zsh
的可能性很大,因为大多数发行版和统一使用似乎都使用sh
,bash
,dash
或ksh
作为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