Linux-Chap3-Shell编程入门

Chap3 Linux Shell编程入门

Shell的工作原理

Shell:用户和操作系统之间的接口。

当用户登录到系统时,有一个shell进程随之启动,并在用户注销时终止。

用户输入的命令时shell的输入。

shell处理命令的步骤:①查找命令中的元字符 ②把这些元字符替换成对应的实际操作参数 ③将重新生成的指令传给内核执行 ④等待指令完成,提示符重新出现,等待下一条命令。

Shell种类:

Bourne系列:

Bourne Shell (/bin/sh) Korn Shell (/bin/ksh) Bash (/bin/bash)

C Shell系列:

C Shell (/bin/csh) Tcsh (/bin/tcsh)


Shell命令元字符

通配符:用来表示文件名的某种模式,在解释时被替换成其他字符。

通配符匹配内容
*任意数量的任意字符
?单个任意字符
[abc]

a,b,c中的任一个字符

[a-z]ASCII码值在a与z中间的任一个字符
[!a-z]不在a-z范围内的任一个字符
!(fname)除fname之外的所有文件名
!(f1|f2)除f1和f2之外的所有文件名
ls .??* //.开头(隐藏文件),≥两个字符长度的文件名
rm *.c //删除以.c结尾的所有文件
rm * .c //删除所有文件(等价于rm *)
ls c*[!0-9] //以c开头,长度任意,结尾不为数字
cp file f[1-3] //cp命令多个参数时默认最后一个参数是一个目录,否则错误
cp f[1-3] file //等价于cp f1 f2 f3 file

转义符:在处理文件名中出现通配符的文件时,常常需要用转义符来防止通配符起作用。

       ①在通配符前使用一个\

\*
\?
\[ \]
\[Enter] 换行继续输入

       ②使用引号

           双引号:禁止通配符替换

           单引号:禁止通配符、变量名和命令替换


Shell脚本

命令替换:

       ①反引号`命令`:使用命令的结果来替换命令。反引号中的被视作命令,输出命令执行结果,相当于调用子程序。

       ②$(命令):整个替换成括号中命令的结果

echo –e "The user list is \n `who`" 
echo The current time is `date`
echo The current time is $(date)

重定向: 

       命令的输入输出流:

              输入和输出终端:键盘、显示器

       命令的输入和输出字符流:

               标准输入流:连接到见键盘的输入

               标准输出流:连接到显示器的输出

               标准错误流:连接到显示器的错误消息输出

       三种标准输入输出源:终端、文件、管道

       输入输出重定向到文件:

文件描述符含义                 
0标准输入
1标准输出
2标准错误
3...

其他文件

- 标准输入(从键盘输入)
    cat -foo
> 输出重定向(覆盖)(为1>简写)
    echo content > file
>> 追加输出重定向
    echo content >> file
< 输入重定向(为1<简写)
    wc < file
2> 标准错误输出重定向
    cat foo 2> errorfile
相互重定向
    1>&2 //标准输出流放入标准错误流
    2>&1 //标准错误流放入标准输出流

过滤器:同时用到输入和输出流的命令。对于过滤器来说,输入输出流的顺序是不重要的。

wc < infile > outfile
wc > outfile < infile
>outfile < infile wc

wh1516@PinkRAY:~/桌面$ touch f1
wh1516@PinkRAY:~/桌面$ echo f1giaof1 >f1
wh1516@PinkRAY:~/桌面$ echo f2giaof2 >f2
wh1516@PinkRAY:~/桌面$ touch f3
wh1516@PinkRAY:~/桌面$ cat - f2 < f1 >f3
wh1516@PinkRAY:~/桌面$ cat f3
f1giaof1
f2giaof2
wh1516@PinkRAY:~/桌面$ cat f2 < f1 > f3
wh1516@PinkRAY:~/桌面$ cat f3
f2giaof2

cat - f2 < f1 > f3 2> f4
//- 从键盘输入读东西 显示f2文件内容 输入重定向到f1内容 输出重定向到f3 错误信息重定向到f4
//- 标准输入流,重定向到f1,实际执行不会输入东西,直接从f1读内容放到-处,拼上f2内容,输出到f3
//去掉-,不把f1当成参数,就没有f1输入了,直接把f2的内容写到f3内

命令组合:使用圆括号()和花括号{}将多个命令组合起来。组合命令由一个子shell执行,共享输入和输出源。组合命令能够共享同一个重定向符号。

( ls -l *.txt; wc *.txt ) > all   //先做左边,再做右边

管道:将一条命令的输出作为另一条命令的输入。

           格式:命令1 | 命令2( | 左边的命令使用标准输出,| 右边的命令使用标准输入

           优点:处理速度快,不产生中间文件结果。

who –a | cat > userlist
(cat f1; echo var2) | wc –l
ls | cat – file | wc     //ls的输出给cat - ,接上file内容,后用wc计算

wh1516@PinkRAY:~/桌面$ who -a | cat > userlist
wh1516@PinkRAY:~/桌面$ cat userlist
系统引导 2020-10-15 14:48
wh1516   ? :0           2020-10-15 14:49   ?      
    1228 (:0)
运行级别 5 2020-10-15 14:49

wh1516@PinkRAY:~/桌面$ echo "1" > 1.txt
wh1516@PinkRAY:~/桌面$ cat 1.txt
1
wh1516@PinkRAY:~/桌面$ ls | cat - 1.txt | wc
     15      15     109
wh1516@PinkRAY:~/桌面$ ls
1.txt  cachelab-handout  CH4            cond_exp.c       lab2  lab4   linuxch6
c      ch3               ch6emp.tar.gz  datalab-handout  lab3  linux  OS

Shell程序变量

环境变量:shell已经定义的变量,如HOME,SHELL,PATH。

       设置环境变量:export 变量名=变量值

       引用环境变量:$变量名

       查看环境变量:env命令

       常用环境变量:

HOME 用户目录
PATH 命令执行路径,用冒号分隔,Shell会按PATH中给出的顺序搜索目录
PWD 当前工作目录的绝对路径名
UID 当前用户的识别号
RANDOM 一个随机数

       设置和修改环境变量:

              ①在shell中直接修改,在shell中生效。

              ②在启动配置文件中修改,在每次登录后生效(自己用户登录时)。

                     系统配置文件:/etc/profile

                     用户配置文件:~\.profile,~/.bashrc

              ③设置路径变量PATH

                     export PATH="$PATH:newpath"

用户自定义变量:

       变量名:必须以字母开头,其他可以是数字和_,区分大小写。

       变量类型:shell变量都是字符串类型。

       变量不需要提前声明。

       变量赋值:variable=value。  //如 route=~/Documents

       变量引用:$var_name(可使用转义符 \ 和单引号来避免替换)

       用户自定义变量的引用和赋值:

变量引用变量替换
$变量名变量值
${变量名}变量值
${#变量名}变量值长度
变量赋值赋值语义
y=${x-value}若x有值,则y=x,否则y=value
y=${x=value}若x没有值,则y=x=value,否则y=x
y=${x+value}若x有值,则y=value,否则不操作
y=${x?value}若x有值,则y=x,否则在标准错误输出value

              大括号把变量名和后面字符串区分开,value缺省,防止x值为空。

变量操作命令${var}:给定变量名,${x}返回变量的值(与$x相同)

       字符串截断和提取:

操作返回值示例:var=~/my/file.txt
${var#s}去掉从边开始第一个匹配s的子串${var#*/}=my/file.txt
${var##s}去掉从边开始最后一个匹配s的子串${var##*/}=file.txt
${var%s}去掉从边开始第一个匹配s的子串${var%/*}=~/my
${var%%s}去掉从边开始最后一个匹配s的子串${var%%/*}=~
${var:m:n}提取从m位置开始往后的n个连续字符${var:2:5}=my/fi

       字符串替换:

操作返回值示例:var=~/my/file.txt
${var/s/t}把第一个匹配s的串替换成t${var/t/e}=~/my/file.ext
${var//s/t}把所有的匹配s的串都替换成t${var//t/e}=~/my/file.exe

运算符:数值运算。

       ①let命令(shell内部命令)【shell所有变量都为字符串类型,let为整型数的运算。let x=1 x为数值。不加let 作字符串处理】

       ②$(( 表达式 )) (shell扩展命令) 【$((括号内变量不加$符号))】

       ③expr命令【逻辑运算 正则表达式匹配】

       ④bc浮点数计算器

let x=1; echo $x
1
let x=$x+1; echo $x
2

x=1
echo $x+1
1+1
echo $((x+1))
2

bc命令:一个支持浮点数运算的计算器。通常采用管道的方式接受输入字符串并返回计算结果。

       常用参数:

              scale=n 保留小数点后n位(整型运算中无效)

              ibase=k 指定输入为k进制

              obase=k 指定输出为k进制

       常用运算符:+,-,*,/,^,%

echo "scale=2;3+3*8" | bc
27
echo "scale=2;obase=2;4^2" | bc
10000
echo "scale=3; 3.8^4" | bc
208.513

数组:

       数组的声明:declare -a 数组变量名

       数组赋值:

              ①array[0]=value0

              ②array=(0 1 2 3)

              ③array=(0 [3]=1 2) //2赋值在第四个位置,前面就是NULL

              ④使用循环语句赋值

       数组引用:

              ${array[i]} 访问数组array的第i个元素

              ${array[*]}或${array[@]} 访问数组array的所有元素

              ${#array[*]}或${#array[@]} 数组array的元素个数

       数组销毁:

              unset array 销毁数组array

              unset array[i] 销毁数组array中的第i个元素


Shell程序语句

shell脚本:将一组命令保存在文件中,然后逐条执行,类似于windows的批处理文件。可以使用各种文件编辑软件来编写shell脚本。创建文件后使用chmod命令使其具有执行权限。运行时要写绝对路径,shell在PATH下搜索有无同名脚本。如在当前目录下,加./。

解释器行:#!bin/bash,在shell脚本的第一行,用来指定运行该脚本的shell种类。#!+脚本路径:/bin/sh or /bin/bash。如不写,用当前shell去解释。

命令行位置参数:运行脚本时给定的用户输入参数。可以通过特定的形式在脚本中引用这些参数。参数之间用空格隔开,类似环境变量,运行脚本程序时系统自动赋值。不能=赋值,只能引用其值。以0开头——命令行位置参数。超过9个参数时,可使用shift命令将参数移位。shift之后前面的变量就消失了,要用其他变量存下。

位置参数说明
$0所执行的命令的名字
$1 -- $9命令行参数1到9的名字
$*所有命令行参数组合成的字符串
$#命令行参数的个数
$$当前shell的进程ID号
$?最近一次命令的退出状态(正常0)
$!最近一次后台进程的ID号

读取用户输入:从标准输入读取用户的输入,存入变量表中的变量。

read 变量表
-p 提示字符串
-n 指定数量读取
-t 指定时间读取
-s 隐藏显示输入字符

read –n 2 –t 10 –p "Input your name and age: " name age

命令退出状态:所有命令和程序都会返回一个退出状态值,可以通过exit命令显示指定脚本的退出状态值。(正常退出 exit 0,错误退出 exit 1)(错误时返回>0)使用exit命令时一种好的编程习惯。可以使用参数$?查看上一条命令的退出状态

wh1516@PinkRAY:~/桌面$ ls demo;echo $?
ls: 无法访问'demo': 没有那个文件或目录
2

Shell控制结构语句:

       顺序执行:在同一行内使用 ; 分隔命令

       条件执行:使用逻辑运算符&&和||分隔命令

              cmd1 && cmd2  若cmd1成功,则执行cmd2

              cmd1 || cmd2     若cmd1失败,则执行cmd2

       命令的成功与否取决于命令的退出状态值。

条件选择语句if:

格式1:
if 条件测试命令
    then条件为真时的命令串 
    else条件为假时的命令串 
fi
格式2:
if 条件测试命令 
    then条件为真时的命令串 
    elif 条件测试命令 
        then 条件为真时的命令串 
        else 条件为假时的命令串 
fi

wh1516@PinkRAY:~/桌面$ cat > if.sh
#!/bin/sh
if [ -z "$*" ]
then
echo "No argument is given"
exit 1
else 
echo "The argument list is $@"
fi
exit
^Z
[1]+  已停止               cat > if.sh
wh1516@PinkRAY:~/桌面$ ls -l if.sh
-rw-r--r-- 1 wh1516 wh1516 109 10月 29 15:09 if.sh
wh1516@PinkRAY:~/桌面$ chmod 744 if.sh
wh1516@PinkRAY:~/桌面$ ls -l if.sh
-rwxr--r-- 1 wh1516 wh1516 109 10月 29 15:09 if.sh
wh1516@PinkRAY:~/桌面$ ./if.sh
No argument is given
wh1516@PinkRAY:~/桌面$ ./if.sh djf dhjf hdsj
The argument list is djf dhjf hdsj

条件测试命令:test命令(缩写[ ])功能:①比较两个数值;②比较两个字符串,或与null进行比较;③查看文件特性。test没有任何输入,只记录退出状态值$?。

数值比较运算符意义                  

-eq

等于
-ne不等于
-gt大于
-ge大于等于
-lt小于
-le小于等于
字符串比较运算符意义
=等于
!=不等于
-n strstr不为空
-z strstr为空
strstr被赋值且不为空
x=1;y=2;z=3
test $x -eq $y;echo $?
1
[ $x -lt $z ];echo $?
0

x="str 1";y="str 2"
[ -n "$x" ];echo $?
0
[ "$x" = "$y" ];echo $?
1

文件特性检查:test命令检查文件特性。

命令意义
[ -e file ]file存在
[ -f file ]file存在并是一个常规文件
[ -d file ]file存在并是一个目录
[ -L file ]file存在并是一个符号链接
[ -rwx file ]file存在且可读可写可执行
[ -s file ]file存在且大小大于0
[ f1 -nt f2 ]f1比f2更新
[ f1 -ot f2 ]f1比f2更旧
[ f1 -ef f2 ]f1被链接到f2

复合条件:可以在if中使用复合条件运算符。

&& 和 ||
if [ "$0"="cmd" ] || [ "$0"="./cmd" ]
-a 和 -o
if [ "$0"="cmd" -o "$0"="./cmd" ]

if判断第一个参数是不是文件
[ -f $1 ]是返回0 不是返回异常
{不可读[ ! -r $1 ]
不可读文件返回exit3
可读输出文件内容}
不是文件 exit2
输出$? 观察exit状态是几
文件名带空格 error ll
[ -f error ll ]报错认为有2个参数
[ -f "error ll" ]加双引号

case语句:按照从上到下的顺序匹配表达式的值,如匹配成功则执行相应的命令串。最后一个模式匹配任何未与之前匹配的表达式。case语句也支持通配符。

case 表达式 in 
    模式1) 命令串1 ;; 
    模式2) 命令串2 ;;
     … 
    模式 *) 命令串n 
esac
//两个分号表示该分支结束 *)相当于default

循环语句for:每次迭代中列表的值被依次赋给变量,并执行循环体。当列表结束时,循环结束。

for 变量 in 列表 
    do
        命令串 
    done

循环语句while:当条件测试命令返回真时,执行循环体。当条件测试命令返回假时,循环结束。

while 条件测试命令
    do
        命令串
    done
两个字符串比较
read 两个参数存在name和number里
输出刚才的两个变量
只要answer不是y 默认为no
输出重定向到addressbook文件中
跟在echo后面的重定向 1&>2 单独重定向到标准错误内(要其显示在终端——交叉重定向or read -p)
最外层while后的重定向作用在里面的每一条echo

循环语句until:当条件测试命令返回假时,执行循环体。当条件测试命令返回真时,循环结束。

until 条件测试命令
    do
        命令串
    done

break和continue:break语句:跳出循环体,执行done之后的语句。continue语句:跳到done的位置,重新执行循环。

shell函数:函数调用:使用函数名进行调用,并可在名称后面给出命令行参数。函数支持对命令行位置参数的引用。函数的退出状态由return返回。函数可通过标准住处向调用者返回输出字符串。

       调用函数时,把要传入的参数放在调用语句后即可,函数内部参数$1,$2之类。answer数值比较,要加上数值表达式。

函数声明:
function(){
    statements
    return value
}

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值