正如goldilocks的评论和人类参考文献所描述的那样,
shift重新分配位置参数($1,$2等),以便$1采用的旧值$2,
$2采用的值$3等。*$1丢弃
旧的值。($0未更改。)执行此操作的某些原因包括:
- 它使您可以更轻松地访问第十个参数(如果有)。
$10不起作用–它被解释为与$1串联0
(因此可能会产生Hello0)。在a之后shift,第十个参数变为$9。(但是,在大多数现代Shell中,您可以使用${10}。)
- 正如Bash初学者指南所演示的那样,它可用于循环遍历参数。恕我直言,这很笨拙;
for对此要好得多。
- 就像您的示例脚本一样,它使您可以轻松地以相同的方式处理所有参数,除了少数几个。例如,在脚本中,
$1和$2是文本字符串,而$3and所有其他参数是文件名。
这就是它的播放方式。假设您的脚本被调用Patryk_script,并且被称为
Patryk_script USSR Russia Treaty1 Atlas2 Pravda3
脚本看到
$1 = USSR
$2 = Russia
$3 = Treaty1
$4 = Atlas2
$5 = Pravda3
该语句ostr="$1"将变量设置ostr为USSR。第一条shift语句按如下所示更改位置参数:
$1 = Russia
$2 = Treaty1
$3 = Atlas2
$4 = Pravda3
该语句nstr="$1"将变量设置nstr为Russia。第二条shift语句按如下方式更改位置参数:
$1 = Treaty1
$2 = Atlas2
$3 = Pravda3
然后for循环变化USSR($ostr)来Russia($nstr在文件中)Treaty1,Atlas2和Pravda3。
脚本存在一些问题。
以$ @归档;做
如果脚本被调用为
Patryk_script苏联俄罗斯条约1“世界地图集2” Pravda3
它看到
1美元=苏联
2美元=俄罗斯
$ 3 =条约1
4美元=世界地图集2
5美元= Pravda3
但是,因为$@没有加引号,在太空World Atlas2中没有报价,并且for循环认为它有四个文件:Treaty1,World,Atlas2,和Pravda3。这应该是
用于“ $ @”中的文件;做
(在参数中引用任何特殊字符)或简单地
对于文件
(相当于更长的版本)。
eval“ sed's /” $ ostr“ /” $ nstr“ / g'$ file”
不必将其设置为eval,并且将未经检查的用户输入传递给eval会很危险。例如,如果脚本被调用为
Patryk_script“'; rm *;'”俄罗斯条约1 Atlas2 Pravda3
它会执行rm *!如果脚本可以比调用它的用户更高的特权运行,这将是一个大问题。例如,它是否可以通过sudoWeb界面运行或从Web界面调用。如果仅在目录中以自己的方式使用它,那么可能就没有那么重要了。但是可以更改为
sed“ s / $ ostr / $ nstr / g”“ $ file”
这仍然有一些风险,但是风险要轻得多。
if [ -f $file ],> $file.tmp而mv $file.tmp $file
应该是if [ -f "$file" ],> "$file.tmp"和mv "$file.tmp" "$file"分别处理,可能在他们的空间(或其他奇怪的字符)的文件名。(该eval "sed …命令还会破坏其中包含空格的文件名。)
* shift带有一个可选参数:一个正整数,它指定要移动多少个参数。默认值为一(1)。例如,shift 4使$5
成为$1,
$6成为$2,等等。(请注意,《Bash初学者指南》中的示例是错误的。)因此,可以将脚本修改为:
ostr="$1"
nstr="$2"
shift 2
可能会更清楚。
结束语 /警告:
Windows命令提示符(批处理文件)语言还支持SHIFT命令,该shift命令与Unix shell中的命令基本上具有相同的功能,但有一个显着的不同,我将隐藏该代码,以防止人们对此感到困惑:
- 像这样的命令
SHIFT 4是错误,产生“对SHIFT命令无效的参数”错误消息。
SHIFT /n,其中n为0到8之间的整数是有效的-但它不会移位times。它从第n 个参数开始偏移一次。因此, 导致(第五个参数)变为,依此类推,仅将参数0到3保留下来。n SHIFT /4%5%4,
%6%5
pushd和popd)。