我有以下脚本:
echo 'Please select type file , the name of the input file and the name of the output file:
a.plain ( please press a ) <input_file> <output_file>;
b.complex ( please press b ) <input_file> <output_file>;'
read one two three
echo $#
if [ $# -ne 3 ]; then
echo "Insufficient arguments !"
exit 1;
else
echo "Number of passed parameters is ok"
fi
$#
始终输出 0 ,当我稍后在脚本中使用 $one 、 $two 和 $third 时,读取命令提供正确的变量
谢谢。
答案1
要测试是否获得所有变量的值并否则退出,请使用测试-z
来测试空字符串:
if [ -z "$one" ] || [ -z "$two" ] || [ -z "$three" ]; then
echo 'Did not get three values' >&2
exit 1
fi
该$#
值是数量位置参数,通常是命令行参数(或set
内置设置的值)。这些在$1
、$2
、等中可用$3
(或共同在数组中"$@"
),并且与内置函数读取的值无关read
。
使您的脚本将输入作为命令行参数而不是交互地读取它们(如果用户要提供一个或多个路径,这可能是首选,因为他们可能会利用制表符完成功能,并且还可以更轻松地使用来自另一个脚本中的脚本并且不需要连接终端),使用
if [ "$#" -ne 3 ]; then
echo 'Did not get three command line arguments' >&2
exit 1
fi
one=$1
two=$2
three=$3
在这种情况下,脚本将运行为
./script.sh a.plain /path/to/inputfile /path/to/outputfile
输入的处理是否可以从标准输入进行,并且输出是否可以发送到标准输出(即,如果您实际上不需要脚本内输入文件和输出文件的显式路径),那么脚本只需采用第一个参数(a.plain
或b.complex
)。
./script.sh a.plain </path/to/inputfile >/path/to/outputfile
然后,该脚本将使用标准输入和标准输出流进行输入和输出(因此只需检查单身的命令行参数)。
这使得可以使用从另一个程序输入的数据来运行脚本,并且还可以进行进一步的后处理:
gzip -dc <file-in.gz | ./script.sh a.plain | sort | gzip -c >file-out.gz
答案2
你做错了什么
您使用读取(在运行时)混淆了输入参数(在启动时的脚本)和用户输入。
$#
报告启动时的参数数量。例如 for ./«script_name» 1 2 3
,当在脚本中使用时,它将返回 3。
答案3
您可以使用该set
命令重新设置位置参数,覆盖以前的值。该IFS
变量指定用作分隔符的字符列表,因此您也可以使用它来解析 CSV。请注意,这set
是一个内置命令,因此覆盖单个命令的变量的常用语法不起作用,因为命令之前指定的变量是命令的简写env
,它将为子进程设置环境。
$#
是当前存在的位置参数的数量。
$ read foo
a b c d e
$ echo $foo
a b c d e
$ set -- $foo
$ echo $#
5
$ IFS=: set -- $foo # doesn't work
$ echo $#
5 # still got 5
$ IFS=:
$ set -- $foo
$ echo $#
1