shell中的for、while和until语句都是Compound Commands
for name [ [ in [ word … ] ] ; ] do list ; done
positional parameter
that is set. The return status is the exit status of the last command that executes. If the expansion of the items following in results in an empty list, no commands are executed, and the return status is 0.A positional parameter is a parameter denoted by one or more digits, other than the single digit 0. Positional parameters are assigned from the shell’s arguments when it is invoked, and may be reassigned using the set builtin command. Positional parameters may not be assigned to with assignment statements. The positional parameters are temporarily replaced when a shell function is executed
for variable in value_list
do
statements
done
in value_list 部分可以省略,省略后的效果相当于将 variable 取值为
positional parameter
for n in 1 2 3 4 5 6
do
echo $n
done
for str in "abc" "390" "tom"
do
echo $str
done
After word splitting, unless the -f option has been set, bash scans each word for the characters *, ?, and [. If one of these characters appears, then the word is regarded as a pattern, and replaced with an alphabetically sorted list of file names matching the pattern.
- * : Matches any string, including the null string.
- ? : Matches any single character.
- […] : Matches any one of the enclosed characters.
for i in hello 1 * 2 goodbye
do
echo "Looping ... i is set to $i"
done
上述命令输出结果为:
Looping ... i is set to hello
Looping ... i is set to 1
Looping ... i is set to (name of first file in current directory)
... etc ...
Looping ... i is set to (name of last file in current directory)
Looping ... i is set to 2
Looping ... i is set to goodbye
Brace expansion is a mechanism by which arbitrary strings may be generated. This mechanism is similar to pathname expansion, but the filenames generated need not exist. Patterns to be brace expanded take the form of an optional preamble, followed by either a series of comma-separated strings or a sequence expression between a pair of braces, followed by an optional postscript. The preamble is prefixed to each string contained within the braces, and the postscript is then appended to each resulting string, expanding left to right.
Brace expansions may be nested. The results of each expanded string are not sorted; left to right order is preserved. For example, a{d,c,b}e expands into ‘ade ace abe’.
A sequence expression takes the form {x…y[…incr]}, where x and y are either integers or single characters, and incr, an optional increment, is an integer. When integers are supplied, the expression expands to each number between x and y, inclusive. Supplied integers may be prefixed with 0 to force each term to have the same width. When either x or y begins with a zero, the shell attempts to force all generated terms to contain the same number of digits, zero-padding where necessary. When characters are supplied, the expression expands to each character lexicographically between x and y, inclusive. Note that both x and y must be of the same type. When the increment is supplied, it is used as the difference between each term. The default increment is 1 or -1 as appropriate.
for n in {1..100}
do
echo $n
done
for c in {A..z}
do
echo $c
done
for c in a{d,c,b}e
do
echo $c
done
for filename in $(ls *.sh)
do
echo $filename
done
for i in $(seq 1 10);
do
echo $i;
done
function func(){
for str in $@
do
echo $str
done
}
func C++ Java Python C#
也可以省略 value_list,省略后 str 取值为 positional parameter
function func(){
for str
do
echo $str
done
}
func C++ Java Python C#
两段命令输出结果等价
for (( expr1 ; expr2 ; expr3 )) ; do list ; done
语法格式
for((exp1; exp2; exp3))
do
statements
done
print a sequence of numbers
语法格式:
expr命令可以实现数值运算、数值或字符串比较、字符串匹配、字符串提取、字符串长度计算等功能。它还具有几个特殊功能,判断变量或参数是否为整数、是否为空、是否为0等。
'expr’支持模式匹配和字符串操作。字符串表达式的优先级高于数值表达式和逻辑关系表达式。
‘STRING : REGEX’
执行模式匹配。两端参数会转换为字符格式,且第二个参数被视为正则表达式,它默认会隐含前缀"^"。随后将第一个参数和正则模式做匹配。
如果匹配成功,且REGEX使用了’(‘和’)‘,则此表达式返回匹配到的,如果未使用’(‘和’)',则返回匹配的字符数。
如果匹配失败,如果REGEX中使用了’(‘和’)',则此表达式返回空字符串,否则返回为0。
只有第一个’(…)‘会引用返回的值;其余的’(…)'只在正则表达式分组时有意义。
在正则表达式中,‘+’,'?‘和’|'分表代表匹配一个或多个,0个或1个以及两端任选其一的意思。
‘match STRING REGEX’
等价于’STRING : REGEX’。
‘substr STRING POSITION LENGTH’
返回STRING字符串中从POSITION开始,长度最大为LENGTH的子串。如果POSITION或LENGTH为负数,0或非数值,则返回空字符串。
‘index STRING CHARSET’
CHARSET中任意单个字符在STRING中最前面的字符位置。如果在STRING中完全不存在CHARSET中的字符,则返回0。
‘length STRING’
返回STRING的字符长度。
‘+ TOKEN’
将TOKEN解析为普通字符串,即使TOKEN是像MATCH或操作符"/"一样的关键字。这使得’expr length + “$x”‘或’expr + “$x” : ‘./(.)'‘可以正常被测试,即使"$x"的值可能是’/‘或’index’关键字。这个操作符是一个GUN扩展。
通用可移植版的应该使用’" $token" : ’ (.)’‘来代替’+ “$token”’。
要让expr将关键字解析为普通的字符,必须使用引号包围。
'expr’支持普通的算术操作,算术表达式优先级低于字符串表达式,高于逻辑关系表达式。
‘+ -’
加减运算。两端参数会转换为整数,如果转换失败则报错。
‘* / %’
乘,除,取模运算。两端参数会转换为整数,如果转换失败则报错。
'expr’支持普通的逻辑连接和逻辑关系。它的优先级最低。
‘|’
如果第一个参数非空且非0,则返回第一个参数的值,否则返回第二个参数的值,但要求第二个参数的值也是非空或非0,否则返回0。如果第一个参数是非空或非0时,不会计算第二个参数。
经过测试,以上手册内容是错误的。正确的应该是:如果第一个参数非0,则返回第一个参数的值,否则返回第二个参数。但如果任意一个参数为空,则报错。除非空字符串使用引号包围,此时将和0的处理方式一样。
‘&’
如果两个参数都非空且非0,则返回第一个参数,否则返回0。如果第一个参为0或为空,则不会计算第二个参数。
经过测试,以上手册内容是错误的。正确的应该是:如果两个参数都非0,则返回第一个参数,否则返回0。但任意一个参数为空,则报错。除非空字符串使用引号包围,此时将和0的处理方式一样。
‘< <= = == != >= >’
比较两端的参数,如果为true,则返回1,否则返回0。"==“是”="的同义词。"expr"首先尝试将两端参数转换为整数,并做算术比较,如果转换失败,则按字符集排序规则做字符比较。
括号’()'可以改变优先级,但使用时需要使用反斜线对括号进行转义。
foo=$(expr $foo + 1)
expr $fname : '.*/\(.*\)' '|' $fname
解释:其中的’|‘是expr中的连接符,只不过是被引号包围防止被shell解析。例如$fname=/etc/hosts,则此表达式返回hosts,如果$fname=filename,则此表达式’|‘的左边为空,所以返回’|'右边的值,即$fname,即返回filename。
expr aaa : 'a\+' # 解释:因为REGEX部分没有使用\(\),所以返回匹配的字符数
=> 3
expr abc : 'a\(.\)c' # 解释:因为REGEX部分使用了\(\),所以返回匹配的字符
=> b
expr index abcdef cz
=> 3
expr index index a # 解释:因为第二个index是关键字
error-> expr: syntax error
expr index + index a # 解释:使用+将index关键字解析为普通字符串
=> 0
语法格式
find [path] [expression]
参数说明 :
path 是要查找的目录路径,可以是一个目录或文件名,也可以是多个路径,多个路径之间用空格分隔,如果未指定路径,则默认为当前目录。
expression 是可选参数,用于指定查找的条件,可以是文件名、文件类型、文件大小等等。
以下列出最常用expression的部分:
find 命令中用于时间的参数如下:
例如:-mtime 0 表示查找今天修改过的文件,-mtime -7 表示查找过去一周以内修改过的文件。
关于时间 n 参数的说明:
其他选项参数:
scp在网络上的主机之间复制文件。它使用ssh进行数据传输,并使用相同的身份验证并提供与 ssh 相同的安全性。如果需要进行身份验证, scp将要求输入密码或密码。
语法格式
scp [可选参数] file_source file_target
参数说明:
示例:
scp local_file remote_username@remote_ip:remote_folder
或者
scp local_file remote_username@remote_ip:remote_file
或者
scp local_file remote_ip:remote_folder
或者
scp local_file remote_ip:remote_file
scp -r local_folder remote_username@remote_ip:remote_folder
或者
scp -r local_folder remote_ip:remote_folder
-l login_name
Specifies the user to log in as on the remote machine. This also may be specified on a per-host basis in the configuration file.
cd -
When a
cd "$OLDPWD" && pwd
which changes to the previous working directory and then writes its name.
语法格式
ssh-copy-id [-i [identity_file]] [user@]machine
该命令将 SSH 密钥复制到远程主机的authorized_keys文件中。如果给出-i选项,则使用身份文件(默认为~/.ssh/id_rsa.pub )
while list; do list; done
until list; do list; done
while condition
do
statements
done
until condition
do
statements
done
语法格式
read [-ers] [-a array] [-d delim] [-i text] [-n nchars] [-N nchars] [-p prompt] [-t timeout] [-u fd] [name ...]
参数说明:
示例
读取文件(以下两种方式等价)
cat /etc/hosts | while read line
do
echo "$line"
done
while read line
do
echo "$line"
done < /etc/hosts
语法格式
case expression in
pattern1)
statement1
;;
pattern2)
statement2
;;
pattern3)
statement3
;;
……
*)
statementn
esac
case、in 和 esac 都是 Shell 关键字,expression 表示表达式,pattern 表示匹配模式。
case 会将 expression 的值与 pattern1、pattern2、pattern3 逐个进行匹配:
语法格式
select variable [in value_list]
do
statements
done
运行到 select 语句后,取值列表 value_list 中的内容会以菜单的形式显示出来,用户输入菜单编号,就表示选中了某个值,这个值就会赋给变量 variable,然后再执行循环体中的 statements(do 和 done 之间的部分)。
每次循环时 select 都会要求用户输入菜单编号,并使用环境变量 PS3 的值作为提示符,PS3 的默认值为#?,修改 PS3 的值就可以修改提示符。
如果用户输入的菜单编号不在范围之内,例如上面我们输入的 9,那么就会给 variable 赋一个空值;如果用户输入一个空值(什么也不输入,直接回车),会重新显示一遍菜单。
注意,select 是无限循环(死循环),输入空值,或者输入的值无效,都不会结束循环,只有遇到 break 语句,或者按下 Ctrl+D 组合键才能结束循环。
示例
PS3="What you like most of the open source system?"
select i in CentOS RedHat Ubuntu
do
echo "Your Select System: "$i
Done
select in 通常和 case in 一起使用,在用户输入不同的编号时可以做出不同的反应。
shell 函数是一个像简单命令一样调用的对象,并使用一组新的位置参数执行复合命令。shell函数声明如下:
[ function ] name () compound-command [redirection]
This defines a function named name. The reserved word function is optional. If the function reserved word is supplied, the parentheses are optional. The body of the function is the compound command compound-command. That command is usually a list of commands between { and }, but may be any command listed under Compound Commands above. compound-command is executed whenever name is specified as the name of a simple command. Any redirections specified when a function is defined are performed when the function is executed. The exit status of a function definition is zero unless a syntax error occurs or a readonly function with the same name already exists. When executed, the exit status of a function is the exit status of the last command executed in the body.
shell 函数(如上述定义)存储一系列命令以供以后执行。当 shell 函数的名称用作简单命令名称时,将执行与该函数名称关联的命令列表。函数在当前 shell 的上下文中执行;没有创建新进程来解释它们(与 shell 脚本的执行进行对比)。当执行函数时,函数的参数在其执行期间成为位置参数。更新特殊参数#以反映更改。特殊参数0不变。当函数执行时, FUNCNAME变量的第一个元素设置为函数的名称。
函数的局部变量可以使用local内置命令来声明。通常,变量及其值在函数及其调用者之间共享。
函数可以是递归的。递归调用的次数没有限制。
语法格式
function name() {
statements
[return value]
}
简化写法,可以不写 function 关键字:
name() {
statements
[return value]
}
如果写了 function 关键字,也可以省略函数名后面的小括号:
function name {
statements
[return value]
}
函数调用
调用 Shell 函数时可以给它传递参数,也可以不传递。如果不传递参数,直接给出函数名字即可。
如果传递参数,那么多个参数之间以空格分隔:
name param1 param2 param3
不管是哪种形式,函数名字后面都不需要带括号。
和其它编程语言不同的是,Shell 函数在定义时不能指明参数,但是在调用时却可以传递参数,并且给它传递什么参数它就接收什么参数。
Shell 也不限制定义和调用的顺序,你可以将定义放在调用的前面,也可以反过来,将定义放在调用的后面。
Bash提供一维索引和关联数组变量。任何变量都可以用作索引数组;内置的declare将显式声明一个数组。数组的大小没有最大限制,也没有对成员进行连续索引或分配的要求。索引数组使用整数(包括算术表达式)引用,并且是从零开始的;使用任意字符串引用关联数组。
如果使用语法name [ subscript ]= value分配任何变量,则会自动创建索引数组。下标 被视为算术表达式,其计算结果必须大于或等于零。要显式声明索引数组,请使用declare -a name。declare -a name [subscript]也被接受;下标被忽略。
关联数组是使用declare -A name创建的。
可以使用declare和readonly内置函数为数组变量指定属性。每个属性适用于数组的所有成员。
数组使用name = ( value 1 … value n )形式的复合赋值进行分配,其中每个值的形式为 [ subscript ]= string。索引数组赋值不需要括号和下标。当分配给索引数组时,如果提供了可选的括号和下标,则该索引被分配;否则,分配的元素的索引是该语句分配的最后一个索引加一。索引从零开始。
分配给关联数组时,需要下标。
这个语法也被内建的declare接受。可以使用上面介绍的 name [ subscript ]= value语法来分配各个数组元素 。
数组的任何元素都可以使用 ${ name [ subscript ]} 引用。需要使用大括号以避免与路径名扩展发生冲突。如果 下标是@或*,则该词将扩展到name的所有成员。仅当单词出现在双引号内时,这些下标才会有所不同。如果单词用双引号引起来,则 ${ name [*]} 扩展为单个单词,每个数组成员的值由 IFS 特殊变量的第一个字符分隔,而 ${ name [@]} 扩展每个数组元素名称为一个单独的单词。当没有数组成员时,${ name[@]} 扩展为空。如果双引号扩展发生在单词内,则第一个参数的扩展与原始单词的开头部分连接,最后一个参数的扩展与原始单词的最后部分连接。这类似于特殊参数*和@的扩展(参见上面的特殊参数)。${# name [ subscript ]} 扩展为 ${ name [ subscript ]}的长度。如果下标是*或@,扩展是数组中元素的数量。引用不带下标的数组变量相当于引用下标为 0 的数组。
如果下标已被赋值,则数组变量被视为已设置。空字符串是有效值。
unset内置函数用于销毁数组。unset name [ subscript ] 破坏索引下标处的数组元素。必须小心避免路径名扩展引起的不良副作用。unset name,其中name是一个数组,或unset name [ subscript ] ,其中下标是*或@,删除整个数组。
declare 、local和readonly内置函数各自接受-a选项来指定索引数组,并接受-A选项来指定关联数组。read内置函数接受-a选项将从标准输入读取的单词列表分配给数组。set和 声明内置函数以允许将数组值重用为赋值的方式显示数组值。
查看数组所有元素: ${A[@]}数组所有参数
查看数组元素个数:${#A[@]}元素个数
删除元素:unset A[2]
字符串替换:
${string/substring/replacement} 使用replacement,来代替第一个匹配的substring
${string//substring/replacement} 使用replacement, 代替所有匹配的substring