【shell简介】
所有的命令都是在shell终端输入并且执行。打开终端就会出现一个提示符。其形式通常有两种:
[root@localhost ~]#
或者
[hcc@localhost ~]$
其实$表示普通用户,#表示超级用户(root user)。超级用户是linux系统中权限最高的用户。
shell脚本通常是以"#!"(shebang)其实的文本文件,如下所示:
#!/bin/bash
linux环境下的任何脚本语言,都是以这样一个被称为shebang的特殊行为起始的。/bin/bash是Bash的路径。关于shebang的解释:#发音为sharp,!发音为bang,因此shebang合起来就表示了#!
linux执行脚本有两种方式:一种是将脚本作为sh的命令行参数,另一种是将脚本作为具有执行权限的可执行文件。
#将脚本作为sh的命令行参数(注意:这种方式脚本的shebang标示符无效)
sh script.sh
#将脚本作为具有执行权限的可执行文件
chmod a+x script.sh #如果该脚本没有执行权限,需要赋予执行权限 ./script.sh #直接运行该脚本,假设脚本在当前目录
如果是以可执行文件的方式来执行脚本的话,shell程序首先会读取脚本的首行,即shebang标示符。如果首行是 #!/bin/bash,那么内部会以如下的命令行来执行该脚本
/bin/bash script.sh
在bash中,每个命令都是通过分号或者换行符来进行分割的
cmd1;cmd2
相当于两条命令
cmd1 cmd2
【终端打印】
1、使用echo完成终端打印
默认情况下,echo会在每次调用后添加一个换行符
[hcc@localhost ~]$ echo "Hello World" Hello World [hcc@localhost ~]$
如果不想换行,可以使用-n阻止echo换行
[hcc@localhost ~]$ echo -n "Hello World" Hello World[hcc@localhost ~]$
echo命令后面的字符串可以有三种形式,分别是:带双引号的字符串、带单引号的字符串、不带符号的字符串。三者之间的区别如下:
(1)带双引号的字符串,不能直接输出!号,如下例
[hcc@localhost ~]$ echo "Hello World!" -bash: !": event not found [hcc@localhost ~]$
在双引号的字符串中一定要输出!号,有两种办法:
#使用转义字符(缺点:转义字符也打印出来了,不推荐)
[hcc@localhost ~]$ echo "Hello World\!" Hello World\! [hcc@localhost ~]$
#首先执行set +H命令,在使用echo打印(推荐)
[hcc@localhost ~]$ set +H [hcc@localhost ~]$ echo "Hello World!" Hello World! [hcc@localhost ~]$
(2)带单引号的字符串,不能识别变量,内容只作为一个字符串输出
#使用单引号,原样的将字符串内容进行输出
[hcc@localhost ~]$ echo ‘$PATH‘ $PATH [hcc@localhost ~]$
(3)不带任何标识的字符串
不带任何标识的字符串,在遇到;号时,命令会被拆分,如下例
[hcc@localhost ~]$ echo $PATH;hello /usr/lib/qt-3.3/bin:/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/hcc/bin -bash: hello: command not found [hcc@localhost ~]$
通过例子可以看到,shell将;号后面的hello当成了第二条命令。
2、echo的转义输出
#使用-e能够完成echo的转义输出
\a 发出警告声; \b 删除前一个字符; \c 最后不加上换行符号; \f 换行但光标仍旧停留在原来的位置; \n 换行且光标移至行首; \r 光标移至行首,但不换行; \t 插入tab; \v 与\f相同; \\ 插入\字符; \nnn 插入nnn(八进制)所代表的ASCII字符;
例子:
[root@localhost ~]# echo -e "1\t2\t3\t" 1 2 3 [root@localhost ~]#
3、echo打印彩色输出
在终端打印彩色非常的好玩,我们可以使用转义序列来实现。
每种颜色对应的颜色码:
重置=0, 黑色=30, 红色=31, 绿色=32, ***=33, 蓝色=34, 洋红=35, 青色=36, 白色=37。 黑色背景=40, 红色背景=41, 绿色背景=42, ***背景=43, 蓝色背景=44, 洋红背景=45, 青色背景=46, 白色背景=47
使用 \e[颜色码m 即可以实现颜色的转义
例子
4、printf进行格式化输出
printf使用的参数和C语言中printf使用的参数一模一样。
默认情况,printf不像echo一样在末尾自动添加换行符,因此需要换行的话,需要加上\n
例子:
[hcc@localhost ~]$ vim printf.sh #!/bin/bash #文件名 printf.sh printf "%-5s %-10s %-4s\n" No Name Mark printf "%-5s %-10s %-4.2f\n" 1 hucc 96.50 printf "%-5s %-10s %-4.2f\n" 2 zhsl 97.50 printf "%-5s %-10s %-4.2f\n" 3 luzh 98.50
执行该脚本:
[hcc@localhost ~]$ chmod a+x printf.sh [hcc@localhost ~]$ ./printf.sh No Name Mark 1 hucc 96.50 2 zhsl 97.50 3 luzh 98.50 [hcc@localhost ~]$
解释:%-5s指明了一个占5个字符的字符串,-表示左对齐,如果不指定-那么默认是右对齐方式的。
5、打印总结
打印总的来说很简单,但是非常常用,属于必须掌握的知识点。
【玩转变量以及环境变量】
在bash中,每一个变量的值的类型都是字符串,无论你给的变量有没有用单引号或者双引号,值都是以字符串的形式进行存储的。
有一些特殊的变量会被shell环境和操作系统用来存储一些特别的值,这类变量就被称为环境变量。
1、查看某个进程的环境变量
#显示瞬间行程 (process) 的动态
[root@localhost ~]# ps PID TTY TIME CMD 28414 pts/0 00:00:00 bash 28433 pts/0 00:00:00 ps [root@localhost ~]#
#查看某个进程的环境变量
[root@localhost ~]# cat /proc/28414/environ USER=rootLOGNAME=rootHOME=/rootPATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/binMAIL=/var/mail/rootSHELL=/bin/bashSSH_CLIENT=192.168.99.100 52296 22SSH_CONNECTION=192.168.99.100 52296 192.168.99.11 22SSH_TTY=/dev/pts/0TERM=linuxSELINUX_ROLE_REQUESTED=SELINUX_LEVEL_REQUESTED=SELINUX_USE_CURRENT_RANGE=[root@localhost ~]#
环境变量之间默认是已\0进行分隔的,可读行不是特别好,我们可以用tr命令将\0替换成\n
[root@localhost ~]# cat /proc/28414/environ |tr "\0" "\n" USER=root LOGNAME=root HOME=/root PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin MAIL=/var/mail/root SHELL=/bin/bash SSH_CLIENT=192.168.99.100 52296 22 SSH_CONNECTION=192.168.99.100 52296 192.168.99.11 22 SSH_TTY=/dev/pts/0 TERM=linux SELINUX_ROLE_REQUESTED= SELINUX_LEVEL_REQUESTED= SELINUX_USE_CURRENT_RANGE= [root@localhost ~]#
2、实战演练
一个变量可以通过以下方式进行复制,注意=号左右都没有空格
name=value # =号左右都没有空格
例子:
[root@localhost ~]# name=hucc [root@localhost ~]# echo $name hucc [root@localhost ~]#
环境变量是未在当前进程中定义,而从父进程继承而来的变量。
例如在安装jdk的时候我们需要指定JAVA_HOME和PATH两个环境变量
export JAVA_HOME=/usr/local/src/jdk1.7.0_55 export PATH=$PATH:$JAVA_HOME/bin
export命令用于设置环境变量
3、补充内容
(1)获得字符串长度
例子:
[root@localhost ~]# num=0123456789 [root@localhost ~]# echo ${#num} 10 [root@localhost ~]#
(2)识别当前的shell版本
[root@localhost ~]# echo $SHELL /bin/bash [root@localhost ~]# echo $0 -bash [root@localhost ~]#
(3)检查是否为超级用户
[root@localhost ~]# vim isRoot.sh #!/bin/bash #文件名:isRoot.sh if [ $UID -ne 0 ];then echo "不是超级管理员,请以超级管理员的身份进行登录" else echo "欢迎你,超级管理员" fi
执行该脚本:
[root@localhost ~]# chmod a+x isRoot.sh [root@localhost ~]# ./isRoot.sh 欢迎你,超级管理员 [root@localhost ~]#
(4)修改Bash提示字符串
#默认的shell提示脚本是在/etc/bashrc文件中定义的
[root@localhost ~]# cat /etc/bashrc | grep PS1 if [ "$PS1" ]; then [ "$PS1" = "\\s-\\v\\\$ " ] && PS1="[\u@\h \W]\\$ " # if [ "$PS1" ]; then # PS1="[\u@\h:\l \W]\\$ " if [ "$PS1" ]; then [root@localhost ~]#
修改提示字符串(只是用变量覆盖了,并没有修改环境变量,如果想要修改环境,可以到/etc/profile中进行修改)
【通过shell进行数学运算】
1、使用let进行数学运算(只能计算整数,推荐使用)
例子:
[root@localhost ~]# num1=4 [root@localhost ~]# num2=5 [root@localhost ~]# result=num1+num2 #没有使用let,直接识别是字符串 [root@localhost ~]# echo $result num1+num2 [root@localhost ~]# let result=num1+num2 #let可以执行算数操作,并且不用加上$ [root@localhost ~]# echo $result 9 [root@localhost ~]# let num1++ #let可以进行自增操作 [root@localhost ~]# echo $num1 5 [root@localhost ~]# let num2-- #let可以进行自减操作 [root@localhost ~]# echo $num2 4 [root@localhost ~]# let num1+=num2 #let的简写算术操作 [root@localhost ~]# echo $num1 9 [root@localhost ~]#
通过例子可以看到,let命令可以直接执行基本的算数操作,并且使用let时,变量名之间不再需要加上$
2、使用[]和(())进行算术操作(只能计算整数)
操作符[]和(())跟使用let命令类似,但是需要加上$标示符,例如
[root@localhost ~]# no1=4 [root@localhost ~]# no2=5 [root@localhost ~]# result=$[no1+no2] #使用[]操作符 [root@localhost ~]# echo $result 9 [root@localhost ~]# result=$((no1-no2)) #使用(())操作符 [root@localhost ~]# echo $result -1 [root@localhost ~]#
3、使用expr进行算术操作(只能计算整数)
expr使用起来也差不多,也需要加上$标示符,例如
[root@localhost ~]# no1=4 [root@localhost ~]# result=$(expr $no1 + 4) [root@localhost ~]# echo $result 8 [root@localhost ~]#
4、使用bc命令进行复杂的算术运算,比如浮点数的运算以及使用高级函数
(1)设定小数的精度
例子:
[root@localhost ~]# echo "8/3"|bc #如果不设定精度,默认计算是整数 2 [root@localhost ~]# echo "scale=2;8/3"|bc #可以在具体操作前用scale设定精度,用;号隔开 2.66 [root@localhost ~]#
(2)进制转换
例子:
[root@localhost ~]# no=90 [root@localhost ~]# echo "obase=2;$no"|bc 1011010 [root@localhost ~]# echo "obase=16;$no"|bc 5A [root@localhost ~]#
(3)计算平方根
例子:
[root@localhost ~]# echo "scale=2;sqrt(30)"|bc 5.47 [root@localhost ~]#
【玩转文件描述符和重定向】
1、预备知识
文件描述符
0---stdin 1---stdout 2---stderr
重定向
> 将输出重定向到文件,会把文件的内容清空。 >> 将输出重定向到文件,追加到末尾,不会把文件的内容清空。
2、实战演练
例子:
[hcc@localhost ~]$ echo "Tom" > out.txt #将输出重定向到文件 [hcc@localhost ~]$ cat out.txt Tom [hcc@localhost ~]$ echo "Jerry" > out.txt #会将文件之前的内容清空 [hcc@localhost ~]$ cat out.txt Jerry [hcc@localhost ~]$ echo "Jim" >> out.txt #不会将文件之前的内容清空 [hcc@localhost ~]$ cat out.txt Jerry Jim [hcc@localhost ~]$
重定向操作符默认使用标准输出。也就是说 >相当于1> >>相当于1>>
对于错误信息的处理
[hcc@localhost ~]$ ls + ls: 无法访问+: 没有那个文件或目录 [hcc@localhost ~]$ echo $? #当一个命令执行错误时,会返回一个非0的状态,这个状态可以从$?变量中获取 2 [hcc@localhost ~]$
下面的例子不会将错误信息打印到文本中,而是会打印到命令窗口:
[hcc@localhost ~]$ ls + > out.txt ls: 无法访问+: 没有那个文件或目录 #在命令窗口打印了 [hcc@localhost ~]$ cat out.txt [hcc@localhost ~]$ #在文件中没有内容,说明没有重定向到文件中
如何将错误信息重定向到文件中:
[hcc@localhost ~]$ ls + 2> out.txt #在命令窗口没有打印出错误信息 [hcc@localhost ~]$ cat out.txt #在文件中有错误信息,说明将错误信息重定向到文件中了 ls: 无法访问+: 没有那个文件或目录 [hcc@localhost ~]$
将错误信息和成功信息分别重定向到分别的文件中
[hcc@localhost ~]$ ls + 1>>out.txt 2>>err.txt #将成功信息重定向out.txt 将错误信息重定向到err.txt [hcc@localhost ~]$ ls 1>>out.txt 2>>err.txt #将成功信息重定向out.txt 将错误信息重定向到err.txt [hcc@localhost ~]$ cat out.txt err.txt out.txt printf.sh [hcc@localhost ~]$ cat err.txt ls: 无法访问+: 没有那个文件或目录 [hcc@localhost ~]$
总结:其实道理很简单,无论是成功信息还是失败信息,如果没有重定向则默认在命令窗口输出,1>或者>只能重定向成功的信息到文件,2>只能重定向错误的信息到文件。
【数组和关联数组】
1、预备知识
数组是shell脚本中非常重要的组成部分,它借助索引将多个独立的数据存储为一个集合。
Bash支持普通数组和关联数组。普通数组只能使用整数作为数组的索引(个人感觉相当于java中的数组),关联数组可以使用字符串作为数组的索引(感觉相当于java中的map,确切的说应该是Properties类)。
2、实战演练
(1)普通数组
普通数组的常用操作:
[hcc@localhost ~]$ a1=("apple" "banana" "orange" "pear") #直接定义普通数组 [hcc@localhost ~]$ a2[0]="Tom" #通过索引-值的方式定义数组 [hcc@localhost ~]$ a2[1]="Jerry" #通过索引-值的方式定义数组 [hcc@localhost ~]$ a2[2]="Kitty" #通过索引-值的方式定义数组 [hcc@localhost ~]$ a2[3]="Jack" #通过索引-值的方式定义数组 [hcc@localhost ~]$ echo ${a1[0]} #通过索引获取数组的值 apple [hcc@localhost ~]$ echo ${a2[*]} #打印整个数组 Tom Jerry Kitty Jack [hcc@localhost ~]$ echo ${a1[@]} #打印整个数组 apple banana orange pear [hcc@localhost ~]$ echo ${#a1[*]} #打印数组的长度 4 [hcc@localhost ~]$
(2)关联数组
关联数组的常用操作:
[hcc@localhost ~]$ declare -A array #关联数组需要声明 [hcc@localhost ~]$ array=([name]="hucc" [age]="23" [address]="五道口") #直接定义 [hcc@localhost ~]$ array[salary]="8000" #通过索引-值的方式添加数组的内容 [hcc@localhost ~]$ echo ${array[name]} #通过索引获取数组的值 hucc [hcc@localhost ~]$ echo ${!array[*]} #打印数组所有的索引,同样适用于普通数组 name age address salary [hcc@localhost ~]$ echo ${array[*]} #打印数组所有的值 hucc 23 五道口 8000 [hcc@localhost ~]$
本文出自 “陌途” 博客,请务必保留此出处http://flycc258.blog.51cto.com/8624126/1615275
原文:http://flycc258.blog.51cto.com/8624126/1615275