#! /bin/bash
if (( $# < 3 )); then
echo "q4312078q old_string new_string file [file...]"
exit 0
else
ostr=""; shift
nstr=""; shift
fi
echo "Replacing \"$ostr\" with \"$nstr\""
for file in $@; do
if [ -f $file ]; then
echo "Working with: $file"
eval "sed 's/"$ostr"/"$nstr"/g' $file" > $file.tmp
mv $file.tmp $file
fi
done
使用
shift
的行的含义是什么?我认为脚本至少应与参数一起使用,以便...?#1 楼
shift
是内置的bash
,可以从参数列表的开头删除参数。假定提供给脚本的3个参数在
,
,
中可用,则对shift
的调用将使
成为新的
。 >有关更多信息,请参见此处:http://ss64.com/bash/shift.html
http://www.tldp.org/LDP/Bash -Beginners-Guide / html / sect_09_07.html
#2 楼
正如goldilocks的评论和人类参考文献所述,shift
重新分配了位置参数(
,
等),因此
继承了
的旧值,
继承了该值
的等值*。
的旧值将被丢弃。 (
保持不变。)执行此操作的某些原因包括:
它使您可以更轻松地访问第十个参数(如果有)。
无法正常工作-解释为0
与Hello0
相连(因此可能会产生类似
shift
的内容)。
之后,第十个参数变为
。 (但是,在大多数现代shell中,您可以使用
for
。)如Bash初学者指南所示,
它可以用于循环遍历参数。
IMNSHO,这很笨拙;
对此要好得多。如您的示例脚本中一样,
它使您可以轻松地以相同的方式处理所有参数,除了少数几个。
例如,在您的脚本中,
和
是文本字符串,而
Patryk_script
和所有其他参数是文件名。所以这是它的播放方式。
假设您的脚本名为
Patryk_script USSR Russia Treaty1 Atlas2 Pravda3
,并且名为 = USSR
= Russia
= Treaty1
= Atlas2
= Pravda3
脚本参见
ostr=""
语句
ostr
将变量USSR
设置为shift
。 第一个
= Russia
= Treaty1
= Atlas2
= Pravda3
语句按如下所示更改位置参数: nstr=""
语句
nstr
将变量Russia
设置为shift
。 第二个
= Treaty1
= Atlas2
= Pravda3
语句按如下方式更改位置参数: for
然后
USSR
循环将文件$ostr
,Russia
和$nstr
中的Treaty1
(Atlas2
)更改为Pravda3
($@
)。
for file in $@; do
如果脚本被调用为
Patryk_script USSR Russia Treaty1 "World Atlas2" Pravda3
/>会看到
= USSR = Russia = Treaty1 = World Atlas2 = Pravda3
但是,由于没有引用
World Atlas2
,所以没有引用for
中的空格,并且
Treaty1
循环认为它具有四个文件:World
,Atlas2
,Pravda3
,和
eval
。 这应该是
for file in "$@"; do
(引用参数中的任何特殊字符)或简单地
for file do
(等效于更长的版本)。
eval "sed 's/"$ostr"/"$nstr"/g' $file"
不需要是
eval
,和将未经检查的用户输入传递给
rm *
可能很危险。 例如,如果脚本被调用为
Patryk_script "'; rm *;'" Russia Treaty1 Atlas2 Pravda3
,它将执行
sudo
! 如果可以以比调用脚本的用户更高的特权运行脚本,这将是一个大问题;例如,是否可以通过
if [ -f $file ]
运行或从Web界面调用。 如果您只是在目录中以自己的方式使用它,可能就没那么重要了。
,但可以将其更改为
sed "s/$ostr/$nstr/g" "$file"
这仍然存在一些风险,但风险要轻得多。
> $file.tmp
, mv $file.tmp $file
和if [ -f "$file" ]
应分别为
> "$file.tmp"
,mv "$file.tmp" "$file"
和eval "sed …
,以处理可能带有空格(或其他有趣字符)的文件名。
(
shift
命令还会处理其中包含空格的文件名。)*
1
带有可选参数:一个正整数,用于指定多少个参数转移。
默认值为1(
shift 4
)。 例如,
导致
,
变成ostr=""
nstr=""
shift 2
,依此类推。 (请注意,《 Bash初学者指南》中的示例是错误的。)
因此您的脚本可以修改为说
SHIFT
,可能会更清楚。
末尾注释/警告:
Windows命令提示符(批处理文件)语言
还支持
shift
命令,与Unix shell中的
SHIFT 4
命令基本相同,有一个明显的不同,
我将其隐藏起来以防止人们对此感到困惑:
SHIFT /n
之类的命令是错误,产生了“对SHIFT命令无效的参数”错误消息。
n
,其中n
是0到8之间的整数,是有效的,但无效移
SHIFT /4
次。 它从第n个参数开始移动一次。
所以
%5
导致%4,
(第五个参数)变为%6
。%5
变为q4312079q,依此类推,仅保留参数0到3。评论
与简单的for循环相比,shift可以应用于while,直到,甚至for循环,以更微妙的方式处理数组。我经常发现它在诸如... set -f-$ args;之类的循环中很有用。 IFS = $ split;对于arg do set-$ arg;移位“ $ {number_of_fields_to_discard}” && fn_that_wants_split_arg“ $ arg”;完成
–mikeserv
2014-12-18在2:37
#3 楼
最简单的解释是这样的。考虑以下命令:/bin/command.sh SET location Cebu
/bin/command.sh SET location Cebu, Philippines 6014
如果没有
shift
的帮助,您将无法提取位置的完整值,因为该值可能会任意长。当您两次移位时,args SET
和location
被删除,使得:x="$@"
echo "location = $x"
凝视
$@
物体很长。这意味着,尽管有空格和逗号,它也可以将完整位置保存到变量x
中。因此,总而言之,我们调用shift
,然后再检索变量$@
剩余的值。 更新
我在下面添加了一个简短的代码片段,显示了
shift
的概念和用途,否则,很难正确提取字段。#!/bin/sh
#
[ $# -eq 0 ] && return 0
a=
shift
b=$@
echo $a
[ -n "$b" ] && echo $b
解释:在
shift
之后,变量b将包含其余所有传入的内容,无论是空格还是其他。[ -n "$b" ] && echo $b
是一种保护,因此我们仅在出现以下情况时才打印b它有内容。评论
(1)这不是最简单的解释。这是一个有趣的角度。 (2)但是,只要您要串联一堆参数(或所有参数),就可能要养成使用“ $ *”而不是“ $ @”的习惯。 (3)我本来要对您的答案表示赞同,但我没有,因为您说的是“两次移位”,但实际上并没有在代码中显示出来。 (4)如果您希望脚本能够从命令行中获取多个单词的值,最好要求用户将整个值放在引号中。 …(续)
–斯科特
18-2-10的2:15
(续)...您今天可能不在乎,但是您的方法不允许您使用多个空格(Philippines6014),前导空格,尾随空格或制表符。 (5)BTW,您也许还可以使用x =“ $ {*:3}”以bash的方式执行此处的操作。
–斯科特
18-2-10的2:15
我试图解释您的“ ***不允许多个空格***”注释的来源,因为这与shift命令无关。您可能是指$ @与$ *的细微差别。但是事实仍然存在,我上面的代码段可以准确地提取位置,无论尾随或前方有多少空间都没有关系。转移后,位置将包含正确的位置。
–本征场
18-3-11的3:11
#4 楼
shift
将命令行参数视为FIFO队列,每次调用时都将popleft元素。
array = [a, b, c]
shift equivalent to
array.popleft
[b, c]
, , can be interpreted as index of the array.
$# is the length of array
评论
+1请注意,它不是在旋转它们,而是将它们移出(参数的)数组。 Shift / unshift和pop / push是这种一般操作的常用名称(例如,参见bash的push和popd)。
–金锁
2014年12月16日22:10
权威参考:gnu.org/software/bash/manual/bashref.html#index-shift
–格伦·杰克曼
2014年12月16日在22:11
@goldilocks非常正确。与其“旋转”,不如我应该更好地找到一种使用另一个单词的方法,例如“将参数在参数变量中前进”。无论如何,我希望本文中的示例和参考文献的链接能够使它们变得清楚。
–人类与和平
2014年12月18日在7:58
尽管脚本中提到了bash,但问题是所有shell都通用的,因此Posix标准适用:pubs.opengroup.org/onlinepubs/9699919799/utilities/…
– calandoa
19年8月14日在11:00