Linux Shell教程 【最全最精简bash教程】

题=C"Linux Shell教程"BS30
本文使用仙符''进行排版。
Linux的Shell脚本是Linux的基础之一,学习Shell语法是Linux的必经之路。下面来讲Shell的语法。

脚本解释器,即shell的种类,有:bash,sh,ash,csh(tcsh),ksh. 注意,bash完全兼容sh,一般写sh类型的或bash类型的(後缀sh)。

开头"#!"後接shell执行环境,如:"#!/bin/sh","#!/bin/bash"

关于sh和bash的区别,简单讲即sh是bash --posix,详细的请自查。

"特别注意,阅读请设置tab长度为4字符宽度,中文为2字符宽度,推荐用notepad++查看以免制表符不对齐。"Cred

"一、shell变量"BS15
定义变量,使用赋值语句,如:variableName=value (等号两边没有空格)。
引用变量,用'$'引用变量,如:$variableName 或 ${variableName} (花括号限定边界)。
重定义变量,直接定义即可。取消变量定义,用unset,如:unset variableName (不能删除只读变量)
只读变量,可以将已定义变量改为只读,如:readonly variableName
显示所有本地shell变量,用set命令即可。
变量类型:1)局部变量,2)环境变量,3)shell特殊变量(命令行参数是特殊变量)

"命令行参数:"B
$0    当前脚本的文件名
$#    传递给脚本或函数的参数个数(不包括$0)。
$*    传递给脚本或函数的所有参数(不包括$0)。
$@    传递给脚本或函数的所有参数(不包括$0)。被双引号包含时,与 $* 稍有不同,下面将会单独讲到。
$?    上个命令的退出状态,或函数的返回值。成功返回0,否则非零(一般为1)。
$$    当前进程的ID
$n    传递给脚本或函数的第n个参数。例如,第一个参数是$1,第二个参数是$2
如果获取第十个及其後的命令行参数,用${n}的形式。

$* 和 $@ 的区别:
前者将参数当做一个整体,後者将参数作为个体连接。所以,$* 和 $@ 是一样的,而"$*" 和 "$@"不一样,有言:
"$*" is equivalent to "$1c$2c...", where c is the first character of the value of the IFS variable.
"$@" is equivalent to "$1" "$2" ...
IFS variable(内部分隔符),有'\040'(空格),'\011'(制表符),'\012'(换行符)。

${*}和${@}的变量替换:
此两者的区别在变量替换,在${ }中使用*和@是有区别的:
"使用@得到结果列表,使用*得到一个字符串"UBCred,如:
${@:0}        得到$0 $1 $2 ... 的结果列表
${*:0}        得到$0 $1 $2 ... 的单个字符串
注意,@和*在花括号里面进行某些高级替换(见字符串操作)时包括$0,而$@(或${@})和$*(或${*})不包括。

"变量引用时判断:"B    注,加星号的行表示其他情况正常引用变量值
${var-DEFAULT}                未声明则取默认值*
${var:-DEFAULT}                未声明或值空则取默认值*
${var=DEFAULT}                未声明则赋默认值*
${var:=DEFAULT}                未声明或值空则赋默认值*
${var+OTHER}                已声明则取他值否则取空值
${var:+OTHER}                已声明且值非空则取他值否则取空值
${var?ERR_MSG}                未声明则打印出错信息*
${var:?ERR_MSG}                未声明或值空则打印出错信息*
${!varname}                    间接引用,以值为访问变量名称的变量引用其值
${!prefix*} 或 ${!prefix@}    扩展为以前缀开头的变量名,以IFS变量的第一个字符分隔
${!name[*]} 或 ${!name[@]}    扩展为数组中已声明元素的索引,以IFS变量的第一个字符分隔
以上标识符(var,DEFAULT,OTHER,ERR_MSG,varname,prefix,name)可以是任意的,其中,大写的(DEFAULT,OTHER,ERR_MSG)可以是字符串。

"字符串:"B
字符串可以用单引号、双引号或不用引号括起来。
单引号字符串,里面任何字符都照原样且不能出现单引号(转义也不可)。
双引号字符串,里面可以引用变量,可以使用转义。
无引号字符串,变量的值、参数等等都可以看为字符串。
字符串操作:
串长            ${#string}
串址子串            ${string:position}                    从position开始的子串
串取子串            ${string:position:length}            从position开始length长度的子串
删除首部最短匹配    ${string#substring}                    从首部匹配子串(有多个匹配则取最短的)并删除
删除首部最长匹配    ${string##substring}                从首部匹配子串(有多个匹配则取最长的)并删除
删除尾部最短匹配    ${string%substring}                    从尾部匹配子串(有多个匹配则取最短的)并删除
删除尾部最长匹配    ${string%%substring}                从尾部匹配子串(有多个匹配则取最长的)并删除
替换第一个子串    ${string/substring/replacement}        查找第一个匹配的子串并替换之
替换所有子串        ${string//substring/replacement}    查找所有匹配的子串并依次替换之
前缀替换            ${string/#substring/replacement}    若前缀匹配则替换之
後缀替换            ${string/%substring/replacement}    若後缀匹配则替换之
注:string是变量名,position是子串位置(为0则串首,可为负数但要小括号括起来,为-1则串尾),substring可为正则表达式。
以下在bash4.0+被支持:
首字符转大写        ${string^}
所有字符转大写    ${string^^}
首字符转小写        ${string,}
所有字符转小写    ${string,,}
解注:
${parameter^pattern}    ${parameter^^pattern}
${parameter,pattern}    ${parameter,,pattern}
扩展parameter值并转换其英文字母的大小写(parameter变量不会改变)。
pattern可省略,等同于'?'(匹配每一个字符)。注意,pattern必须是一个字符而非字符串。
'^'操作符将匹配pattern的小写字母转换为大写;','操作符将匹配pattern的大写字母转换为小写。
"^^"和",,"则在扩展后的值中转换每一个匹配的字符,'^'和','操作符只匹配首字符并处理。
若parameter是'@'或'*',则此操作依次作用于每个位置参数并得到结果列表。
若parameter是数组变量且下标是'@'或'*',则此操作依次作用于数组所有成员并得到结果列表。

"数组:"B
数组定义:array_name=(value1 ... valuen)    括号里面允许换行,value以空格或换行分隔
也可以单独定义数组各个分量:array_name[i]=valuei    (i可以是数字)
即数组可以不定义就使用,也可以定义时赋初值,数组元素就像普通变量一样使用即可。
引用数组所有元素:${array_name[*]} 或 ${array_name[@]}    只会取得数组已定义元素值的列表
可以使用unset删除数组元素;使用${#array_name[*]}或${#array_name[@]}取得数组已定义的元素数量(数组长度),使用${#array_name[n]}取得n号元素的长度,这些就像求串长一样。
数组切片:${array_name[*]:position:length}或${array_name[@]:position:length},这其实是对数组已定义元素值的列表进行切片,就像串取子串一样。
就是说之前提到的字符串操作实际上是视字符串为列表的操作,同样能作用于数组构建的列表。


"二、shell语句"BS15
"注释语句:"B以'#'开头的行为注释,没有类似C/C++语言的多行注释。

"条件语句:"B
有三种格式:
if [ expression ] then ... fi
if [ expression ] then ... else ... fi
if [ expression ] then ... elif [ expression2 ] then ... else ... fi
可以写成一行也可以多行,如:
if test $[num1] -eq $[num2]; then echo 'equal'; elif test $[num1] -lt $[num2]; then echo 'less'; else echo 'greater'; fi;
或者:
if test $[num1] -eq $[num2]
then
  echo 'equal'
elif test $[num1] -lt $[num2]
then
  echo 'less'
else
  echo 'greater'
fi

"循环语句:"B
for循环:
for var in list
do
  command...
done
for循环还支持类C语言格式:
for (( expr1 ; expr2 ; expr3 )) ; do commands ; done

while循环:
while command
do
  Statements to be executed if command is true(return 0).
done

until循环:(和while循环测试条件正好相反)
until command
do
  Statements to be executed until command is true(return 0).
done

"分支语句:"B
类似C语言的switch-case语句,shell里面有case-esac格式的分支语句:
case var in
mode1)
  command...
  ;;
mode2)
  command...
  ;;
*)
  command...
  ;;
esac
以上分支语句,依次匹配var于mode1,mode2,*,mode是正则表达式,支持'*','?','[abc]','[a-n]'字符和'|'或运算,";;"必须有且在里面表示break(跳出case语句)。

"选择项语句:"B
select name in list
do
  statements that can use  $name...
done
产生list列表中的菜单项供选择(以数字键选择),然後循环执行do-done之间的语句,在循环中可以用break跳出。另外,select命令使用PS3提示符,默认为"#? ",可以用PS3='string'来改变提示字符串。select语句可以搭配case语句。

"函数:"BCred
shell函数很重要,由于shell逐行执行,shell 函数必须先定义后使用。
[function] funname [()] # function关键字和"()"必须有一个
{
  command;
  [return int;]
} # 花括号可以换成小括号,区别见特殊字符
以上方括号"[]"中代表可选内容,如果不用return关键字则以最後一条命令的运行结果作为返回值(0-255之间)。"shell函数可以传参,就像命令一样使用函数,就像脚本一样编写函数。"Cred
函数里面可以定义全局变量(默认)和局部变量(local修饰,如:local var=value)。
"local变量的作用域"B
local变量一般只能在函数中定义,它在函数体中有效且会屏蔽同名全局变量,即使是函数中调用的子函数也能访问到该变量,所以一般在函数中定义变量都应该加上local关键字。
"通用退出状态码:"B
0        命令成功结束
1        通用未知错误
2        误用Shell命令
126        命令不可执行
127        没找到命令
128        无效退出参数
128+x    Linux信号x的严重错误
130        命令通过Ctrl+C终止
255        退出状态码越界


"三、shell运算"BS15
shell是命令式语言(实际上bash內建了一些命令或扩展来支持运算)。

"算术扩展:"B
((expression)) # 可以用$((expression))引用表达式的值,也可以用$[expression]
表达式值零则返回1否则返回0(退出状态码,0表示true,1表示false)。
expression计算整数运算,写法和C语言的表达式一样(支持同样的运算符),此外还支持:
"**"    指数运算
'#'        进制数,如:"base#n"表示以base为进制的数n,base范围[2,64],数字以此取[0,9],[a,b],[A,B],'@','_'.

"expr命令:"B
expr命令可以实现数值计算、字符串操作,这里只讲有关数值计算(整数运算)的内容:
需注意,不能直接使用关键字和特殊字符(需用'\'转义),用参数传递,然後expr命令输出表达式值,所以参与运算的参数要用空格分开,运算符也要分开。
支持的运算符:数值'+','-','*','/','%',"()";数值或字符串比较'<',"<=",'=',"==","!=",">=",'>'.
注意,以上运算符中,'*'需转义,写作"\*",同样需要转义的字符有:'(',')','<','>'.

"[命令和test命令:"B
[命令是bash内建命令,和test命令作用是等同的,'['调用test命令标识,']'关闭条件判断,因为是命令,所以参数要隔开。
'='        字符串相等
"!="    字符串不等
"=="    同'='
'\>'    字符串ASCII码大于
'\<'    字符串ASCII码小于
-z        串长是否值零
-n        串长是否非零
[ str ]    字符串是否非空(注意字符串比较时最好加双引号,以免空字符串导致错误而可能被解析为[ str ]类型)
-eq        数值相等
-ne        数值不等
-gt        数值大于
-lt        数值小于
-ge        数值大于等于
-le        数值小于等于
'!'        逻辑非
-o        逻辑或
-a        逻辑与
-b        文件是否块设备
-c        文件是否字符设备
-d        文件是否目录
-f        文件是否普通文件
-g        文件是否设置了SGID位
-k        文件是否设置了粘着位
-p        文件是否有名管道
-u        文件是否设置了SUID位
-r        文件是否可读
-w        文件是否可写
-x        文件是否可执行
-s        文件是否非空(文件大小非零)
-e        文件是否存在

"[[关键字:"B
[[是bash的关键字而非命令(它不是posix通用的),在[[和]]之间不进行文件名展开和分词,但会参数扩展和命令替换。
文件名展开(filename expansion),例如,*展开为当前工作目录下所有文件。
分词(word splitting),例如,一个带空格的参数可能被分割成多个参数。
[[作用与[作用基本一样,不同的是:
[ ] 使用            [[ ]] 使用
-a    -o                &&    ||
\<    \>                <    >        注意别滥用比较运算符(不可用于数值比较)
数学运算符只能在[[ ]]中使用,有:'+','-','*','/','%',另外在[[ ]]中还有:
当使用 `==' 和 `!=' 操作符时,操作符右边的字符串被用作模式并且执行一个匹配。
当使用 `=~' 操作符时,操作符右边的字符串被当作正则表达式来进行匹配。
由于没有文件名展开和分词,所以在字符串比较时可以不加双引号引用变量。

"let命令:"B
let expression # 基本等价于((expression)),但有少许区别:
let用空格分隔多个表达式,而(( ))用逗号分隔。

"declare -i:"B
通过"declare -i",可以定义整型变量,这样就能进行'+','-','*','/','%'运算了(要求参与运算的都是整型变量并且赋值给整型变量),如:
declare -i m n ret
m=10
n=30
ret=$m*$n+m-n # 可以直接用运算符,直接用变量
echo $ret

"bc命令:"B
bc是Linux下的计算器,一般用如下格式:
ret=`echo expression | bc`
如:ret=`echo sqrt\($a\) | bc` 或 ret=`echo "scale=10;sqrt($a)" | bc`
bc计算器可以进行很多种运算,支持浮点运算。


"四、shell特殊字符"BS15
"转义字符:"B
'\a'    响铃(BEL)
'\b'    退格(BS),将当前位置移到前一列
'\c'    配合"echo -e"使用才会转义生效,取消其及之後的所有字符(包括换行符),一般用于echo取消换行符
'\f'    换页(FF),将当前位置移到下页开头
'\n'    换行(LF),将当前位置移到下一行开头
'\r'    回车(CR),将当前位置移到本行开头
'\t'    水平制表符(HT)
'\v'    垂直制表符(VT)
'\\'    反斜杠字符

注意,以下显示有误(当然整篇排版有误影响不大)故用代码如下:

'\ ','\(','\)','\[','\]','\{','\}'等等    用于使之不做特殊用途

 

"输入输出重定向:"B
文件描述符,除stdin(0),stdout(1),stderr(2)外,用户可定义3~max的文件描述符,可以通过文件描述符重定向输入输出。
输出重定向符:'>'
'>'        覆盖输出
">>"    追加输出
command > filename            把标准输出重定向到一个文件中(覆盖)
command > filename 2>&1        把标准输出和错误一起重定向到一个文件中(覆盖)
command 2 > filename        把标准错误重定向到一个文件中(覆盖)
command 2 >> filename        把标准输出重定向到一个文件中(追加)
command >> filename 2>&1    把标准输出和错误一起重定向到一个文件(追加)
输入重定向符:'<'
command [fd] < file 或文件描述符或设备(fd是文件描述符,此处默认为0)
还有:
'<<<'    字符串输入,如:cat <<< "string"
'<<'    文档输入,如:
cat << EOF > /tmp/file
hello
$name
EOF
给第一个EOF加上双引号,文档内容就不会有变量替换了。
"高级重定向:"BU
exec命令可以更改标准输入输出文件描述符并影响接下来执行的命令。
exec > file # 更改标准输出到文件
exec < file # 更改标准输入自文件
它还可以打开一个文件:exec N<> FILENAME # 重定向符也可使用'<','>'
关闭文件:exec N<&- 或 exec N>&- # exec可省略
文件描述符复制:
[exec] [M]>&N #省略[M]则默认为1        exec是可选项,可换成其他命令
[exec] [M]<&N #省略[M]则默认为0
文件描述符移动:
[exec] [M]>&N- #省略[M]则默认为1        等价于:[exec] [M]>&N;N>&-
[exec] [M]<&N- #省略[M]则默认为0        等价于:[exec] [M]<&N;N<&-

"变量替换:"B
$varname    引用变量
${ }        变量替换,详见shell变量
$( )        命令替换,等同于` `
$(( ))        替换为表达式值
$[ ]        等同于$(( ))

"其他特殊字符:"B
.        点号,文件包含符,作用同source命令,在目录操作中,也表示当前目录,两个点号则表示上一级目录
#        井号,单行注释,首行#!表示shell类型,或者是在变量替换中有特殊作用
~        波浪号,帐户的home目录,等价于$HOME
;        分号,分隔连续命令
;;        连续分号,从case语句中跳出
'        单引号,表示字符串,里面任何字符都照原样且不能出现单引号
"        双引号,表示字符串,里面可以引用变量,可以使用转义
`        反引号,命令替换,用于获取其中的命令输出,`command`等价于$(command)
\        反斜杠,转义字符
|        竖线,管道符,左边命令标准输出作为右边命令标准输入
:        冒号,bash内建命令,仅返回状态值0
?        问号,文件名展开中代表任意一个字符
*        星号,文件名展开中代表任何字符串
$        钱号,变量替换
( )        小括号,命令群组(会生成子shell),在'$( )'中做命令替换,用于定义函数,还用于定义数组
(( ))    双小括号,bash的算术扩展,在变量替换中引用表达式值,还用于C语言风格的for循环
{ }        大括号,命令群组(不生成子shell),相当于匿名函数;在文件名展开中做通配符扩展
[ ]        方括号,等同test命令,或在'$[ ]'中等价于'$(( ))',或者是在通配符中匹配范围内一个字符
[[ ]]    双方括号,[[关键字,用于某些运算
||        shell逻辑或,从左向右执行,直到命令返回成功或执行完毕
&&        shell逻辑与,从左向右执行,直到命令返回失败或执行完毕
!        shell逻辑非,将命令返回值取非,若command返回0则! command返回1,否则! command返回0
&        与号,置于命令结尾,表示将该命令置于後台工作,或者是在文件描述符中有特殊作用
^        在通配符中表示匹配范围之外,如:[^0-9]将不匹配数字,注意,通配符不被bash展开但被某些命令接受
> >>        输出重定向
< << <<<    输入重定向
-        减号,在某些命令中表示标准输入或输出流
<(command)        进程替换,command命令置于後台异步写入到一个虚拟文件,<(command)被替换为该虚拟文件名
>(command)        进程替换,command命令置于後台异步读取到一个虚拟文件,<(command)被替换为该虚拟文件名
"文件名展开中的通配符扩展"U
大括号的作用,注意展开後得到的是结果列表,如:
{a,b,c}{1,2}    展开为    a1 a2 b1 b2 c1 c2
{1..5}            展开为    1 2 3 4 5


"五、shell命令"BS15
echo            屏幕输出
printf            格式输出(类似C语言的printf函数,format_string的含义都一样)
    printf format_string [arguments...]    如:printf %d $var1 123
    与C语言的printf函数区别如下:
    printf 命令不用加括号
    format_string 可以没有引号,但最好加上,单引号双引号均可。
    参数多于格式控制符(%)时,format_string 可以重用,可以将所有参数都转换。
    arguments 使用空格分隔,不用逗号。
source            文件包含,如:source filename.sh
shift            删除参数列表中前n个参数,默认删除第一个参数

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值