shell的学习
一.简述shell:
shell在官方的定义是linux内核的外壳,提供外部与Linux内核之间交互的工具。shell是一种语言,具有跨平台移植性,有多个版本如csh,ksh,sh。个人用的最多的是bash,Linux 操作系统缺省的 shell 是Bourne Again shell,它是 Bourne shell 的扩展,简称 Bash。
查看当前使用的shell类别:
[email protected]-unknown85879:/home/zhugeling$ which sh
/bin/sh
[email protected]-unknown85879:/home/zhugeling$ ls -l /bin/sh
lrwxrwxrwx 1 root root 4 Nov 13 12:01 /bin/sh -> bash
二、如何学习shell?
个人感悟:其实shell的语法跟C语言差不多,但是shell还有很多可供使用的很多强大的命令,如sed,awk,grep等,实用性更强。在学习过程中,基础语法并不是很多,但是结合正则表达是和各种命令之后,变得很灵活。个人的感觉是在理解shell的解析原理基础上要多练习,多练习,多练习!!!不然记不住那么多命令,参数等等。
三、学习shell基础语法
1、变量:
(1)shell的变量不需要特殊声明,引用的时候要在前面用$符号。
(2)变量的赋值,对空格比较敏感,如:
[[email protected] ~]# myvalue= 123
-bash: 123: command not found
[[email protected] ~]# myvalue =123
-bash: myvalue: command not found
[[email protected] ~]# myvalue=123
[[email protected] ~]# echo $myvalue
123
变量赋值时,”=”号两边不能有空格
另外引用变量时,尽量用{} 确定变量的范围,变量名不能含有内置变量(shell的特殊变量)。
双引号和单引号对变量的影响
单引号里用$引用的变量将失效:
[email protected]-unknown85879:~/tmp$ name=zhugeling
[email protected]-unknown85879:~/tmp$ echo $name
zhugeling
[email protected]-unknown85879:~/tmp$ sayhello="Hello $name"
[email protected]-unknown85879:~/tmp$ echo $sayhello
Hello zhugeling
[email protected]-unknown85879:~/tmp$ sayhello=‘Hello $name‘
[email protected]-unknown85879:~/tmp$ echo $sayhello
Hello $name
(3)shell的特殊变量:
shell有一些特殊变量,这些变量经常在脚本用回用到,有必要学会如何使用。
$0 当前脚本的文件名
$n 传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第一个参数是$1,第二个参数是$2。
$# 传递给脚本或函数的参数个数。
$* 传递给脚本或函数的所有参数。
[email protected] 传递给脚本或函数的所有参数。被双引号(" ")包含时,与 $* 稍有不同,下面将会用测试用例讲到。
$? 上个命令的退出状态,或函数的返回值。一般情况下,大部分命令执行成功会返回 0,失败返回 1。
$$ 当前Shell进程ID。对于 Shell 脚本,就是这些脚本所在的进程ID。
测试变量:
测试示例1:输出各个内置变量的含义值
[[email protected] tmp]# cat test.sh
#!/bin/bash
a=$0
b=$2
c=$#
d=$*
e=[email protected]
f=$?
g=$$
echo $a
echo $b
echo $c
echo $d
echo $e
echo $f
echo $g
输入1,2,3参数,输出:
[[email protected] tmp]# sh test.sh 1 2 3
test.sh
2
3
1 2 3
1 2 3
0
26583
测试示例2:研究?和@的区别
[email protected]-unknown85880:~/tmp$ cat test.sh
#!/bin/bash
for var in "$*"
do
echo "* is $var"
done
for var in "[email protected]"
do
echo "@ is $var"
done
[email protected]-unknown85880:~/tmp$ sh test.sh 1 3 5 6
* is 1 3 5 6
@ is 1
@ is 3
@ is 5
@ is 6
区别:?在同一行了,而@则逐个换行了,怀疑是 $* 把所有参数当成一个变量了,我们修改脚本测试一下,加入自加变量并输出。
[email protected]-unknown85880:~/tmp$ cat test.sh
#!/bin/bash
i=0
j=0
for var in "$*"
do
echo "* is $var"
i=$((i+1))
echo "i is $i"
done
for var in "[email protected]"
do
j=$((j+1))
echo "j is $j"
echo "@ is $var"
done
[email protected]-unknown85880:~/tmp$ sh test.sh 1 3 5 6
* is 1 3 5 6
i is 1
j is 1
@ is 1
j is 2
@ is 3
j is 3
@ is 5
j is 4
@ is
可以确认他们的区别就是,当引用@和* 的使用,如果用双引号扩起来,则?是会变成一个变量值,而@则是会按空格区分多个变量,如果输入的参数 类似 “a d”,也会被当成一个变量。
(4)获取用户输入为变量赋值:
[email protected]-unknown85879:~$ cat test.sh
#!/bin/bash
echo -e "input your name:"
read name
echo "your name is $name !"
[email protected]-unknown85879:~$ sh test.sh
input your name:
zhugeling
your name is zhugeling !
2、数组:
shell也是一种语言,数组也是必不可少的,数组也是一种变量,组合变量。
shell的数组下标是用中括号括起来,从0开始计算第一个数组变量,声明时可以直接赋给值,用空格分隔开变量值。
数组使用示例:
[email protected]-unknown85879:~$ cat test.sh
#!/bin/bash
#空数组arr1
arr1=()
arr2=(1 2 3 4 5 6)
echo ${arr2[0]}
echo ${arr2[5]}
[email protected]-unknown85879:~$ sh test.sh
1
6
数组可以参与循环的使用:
for循环引用数组的时候,数组的下标用@符号,其含义可以参看前面的特殊变量说明,将@换成*也可以实现下面的效果。
[email protected]-unknown85879:~$ cat test.sh
#!/bin/bash
#空数组arr1
arr1=()
arr2=(1 2 3 4 5 6)
for var in ${arr2[@]}
do
echo "i am $var !"
done
[email protected]-unknown85879:~$ sh test.sh
i am 1 !
i am 2 !
i am 3 !
i am 4 !
i am 5 !
i am 6 !
3、if判断语句:
算术比较运算符
num1 -eq num2 等于 [ 3 -eq $mynum ]
num1 -ne num2 不等于 [ 3 -ne $mynum ]
num1 -lt num2 小于 [ 3 -lt $mynum ]
num1 -le num2 小于或等于 [ 3 -le $mynum ]
num1 -gt num2 大于 [ 3 -gt $mynum ]
num1 -ge num2 大于或等于 [ 3 -ge $mynum ]
[ -z " $num" ] 等于零
= 两个字符相等
!= 两个字符不等
-n 非空串 不为空
–b 当file存在并且是块文件时返回真
-c 当file存在并且是字符文件时返回真
-d 当pathname存在并且是一个目录时返回真
-e 当pathname指定的文件或目录存在时返回真
-f 当file存在并且是正规文件时返回真
-g 当由pathname指定的文件或目录存在并且设置了SGID位时返回为真
-h 当file存在并且是符号链接文件时返回真,该选项在一些老系统上无效
-k 当由pathname指定的文件或目录存在并且设置了“粘滞”位时返回真
-p 当file存在并且是命令管道时返回为真
-r 当由pathname指定的文件或目录存在并且可读时返回为真
-s 当file存在文件大小大于0时返回真
-u 当由pathname指定的文件或目录存在并且设置了SUID位时返回真
-x 当由pathname指定的文件或目录存在并且可执行时返回真。一个目录为了它的内容被访问必然是可执行的。
-o 当由pathname指定的文件或目录存在并且被子当前进程的有效用户ID所指定的用户拥有时返回真
语法:
(1)单分支:
if 判断条件;then
.......
fi
(2)双分支:
if 判断条件;then
.....
else
....
fi
(3)多分支会用到elif: 注意elif 也要带 then
例如:
if [[ "$x" -le "100" ]];then
echo "good."
elif [[ "$x" -lt "60" ]];then
echo "ok."
else
echo "Unknow argument...."
fi
常见用法:
(1)判断脚本程序中前一句的执行情况:
$? 为0则是执行成功,1则失败
[email protected]-unknown85879:~$ cat test.sh
#!/bin/bash
cd /home/zhugeling
if [ $? -eq 0 ];then
echo "success"
else
echo "fail"
fi
[email protected]-unknown85879:~$ sh test.sh
success
(2)、判断用户输入的参数是否为空:
[email protected]-unknown85879:~$ cat test.sh
#!/bin/bash
read -p "input your name:" name
if [ ! -n "$name" ] ;then
echo "your input is null !"
else
echo "your input is $name"
fi
[email protected]-unknown85879:~$ sh test.sh
input your name:zhugeling
your input is zhugeling
[email protected]-unknown85879:~$ sh test.sh
input your name:
your input is null !
(3)、判断文件夹是否存在,判断文件是否存在:
[email protected]-unknown85879:~$ cat test.sh
#!/bin/bash
read -p "input your file :" file
if [ -d "$file" ]
then
echo "diretory $file found."
else
echo "diretory $file not found."
fi
if [ -f "$file" ]
then
echo "file $file found."
else
echo "file $file not found."
fi
[email protected]-unknown85879:~$ sh test.sh
input your file :tmp
diretory tmp found.
file tmp not found.
[email protected]-unknown85879:~$ sh test.sh
input your file :test.sh
diretory test.sh not found.
file test.sh found.
(4)判断字符串或数值等于,大于,小于等:
[email protected]-unknown85879:~$ cat test.sh
#!/bin/bash
read -p "input your number1 :" number1
read -p "input your number2 :" number2
if [ $number1 -eq $number2 ]
then
echo "$number1 等于 $number2."
elif [ $number1 -gt $number2 ]
then
echo "$number1 大于 $number2 "
else
echo "$number1 小于 $number2 "
fi
[email protected]-unknown85879:~$ sh test.sh
input your number1 :12
input your number2 :13
12 小于 13
[email protected]-unknown85879:~$ sh test.sh
input your number1 :18
input your number2 :16
18 大于 16
[email protected]-unknown85879:~$ sh test.sh
input your number1 :12
input your number2 :12
12 等于 12.
上面判断的变量值还可以是字符串,用于字符串是否与预期的一致等。
判断字符串是否相等 不能用 -eq 要用: = 或 ==号:
if [ “var"="var2“ ] ;then
….
fi
4、shell的循环
(1)for循环
语法格式:
格式1:
for 变量 in 列表值1 列表值2 ... 列表n值
do
语句1
语句2
...
语句n
done
示例:看看下面两种循环条件的写法,保证 in后面的是一组有值的变量或常量。
[email protected]-unknown85879:~$ cat test.sh
#!/bin/bash
read -p "input your number1 :" number1
read -p "input your number2 :" number2
for var in $(seq $number1 $number2)
do
echo "now is $var"
done
for var in {1..3}
do
echo "now $var"
done
[email protected]-unknown85879:~$ sh test.sh
input your number1 :1
input your number2 :4
now is 1
now is 2
now is 3
now is 4
now 1
now 2
now 3
格式2:类似C语言格式
for ((初始值;判断条件;步长值))
do
语句1
语句2
...
语句n
done
示例:
#!/bin/bash
read -p "input your number1 :" number1
read -p "input your number2 :" number2
for((i=$number1;i<$number2;i++))
do
echo "now is $i"
done
[email protected]-unknown85879:~$ sh test.sh
input your number1 :1
input your number2 :3
now is 1
now is 2
(2)、while循环
格式1:
while [ $num -le $num2 ] ------两个变量之间
do
语句1
语句2
...
语句n
num =$((num+1)) ----------变量自加方式1
done
格式2:
while [ $num -le $num2 ] ------两个变量之间
do
语句1
语句2
...
语句n
num=` expr $num + 1` ---变量自加方式2
done
示例:
[email protected]-unknown85879:~$ cat test.sh
#!/bin/bash
read -p "input your number1 :" number1
read -p "input your number2 :" number2
i=$number1
#while [ $i -le $number2 ]
while (($i<$number2))
do
echo "now is $i"
i=$(($i+1))
done
[email protected]-unknown85879:~$ sh test.sh
input your number1 :1
input your number2 :3
now is 1
now is 2
(3)、循环的常见用处:
按文件列表循环:
[email protected]-unknown85879:~$ cat test.sh
#!/bin/bash
read -p "inputh your dir:" dir
for var in `ls $dir`
do
echo "file is $var"
done
[email protected]-unknown85879:~$ sh test.sh
inputh your dir:/home/zhugeling/tmp
file is test1.txt
file is test2.txt
file is test3.txt
批量创建用户或文件(这里以创建文件示例):
[email protected]-unknown85879:~$ cat test.sh
#!/bin/bash
dir=/home/zhugeling/tmp
cd $dir
for var in {1..10}
do
touch filename$var
done
[email protected]-unknown85879:~$ sh test.sh
[email protected]-unknown85879:~$ cd tmp/
[email protected]-unknown85879:~/tmp$ ls
filename1 filename10 filename2 filename3 filename4 filename5 filename6 filename7 filename8 filename9
循环检测一个IP段的连通性:
[email protected]-unknown85879:~$ cat test.sh
#!/bin/bash
for var in {1..20}
do
ping -c2 10.83.3.$var &>/dev/null
if [ $? -eq 0 ];then
echo "10.83.3.$var is exist !"
else
echo "10.83.3.$var is not exist !"
fi
done
[email protected]-unknown85879:~$ sh test.sh
10.83.3.1 is exist !
10.83.3.2 is not exist !
10.83.3.3 is not exist !
10.83.3.4 is not exist !
10.83.3.5 is not exist !
10.83.3.6 is not exist !
10.83.3.7 is not exist !
10.83.3.8 is not exist !
10.83.3.9 is not exist !
10.83.3.10 is exist !
10.83.3.11 is exist !
10.83.3.12 is exist !
10.83.3.13 is exist !
10.83.3.14 is exist !
10.83.3.15 is exist !
10.83.3.16 is exist !
10.83.3.17 is exist !
10.83.3.18 is exist !
10.83.3.19 is exist !
10.83.3.20 is exist !
此外循环还可以用于统计数值,循环执行某些命令等用途。
5、shell的分支case
shell的分支是用case语句控制,语法如下:
case 值 in
模式1)
命令1
...
;;
模式2)
命令2
...
;;
......
esac
简单示例:
[email protected]-unknown85879:~$ cat test.sh
#!/bin/bash
case $1 in
start )
echo "server is starting !"
;;
stop )
echo "server is stopping !"
;;
restart)
echo "server is restarting !"
;;
*)
echo "you input is error,please try again!"
;;
esac
[email protected]-unknown85879:~$ sh test.sh stop
server is stopping !
[email protected]-unknown85879:~$ sh test.sh
you input is error,please try again!
[email protected]-unknown85879:~$ sh test.sh start
server is starting !
加参数选项的示例:
#!/bin/bash
while getopts :b:d: OPT &> /dev/null;
do
case $OPT in
b)
echo "is b"
echo $OPTARG
;;
d)
echo "is d"
echo $OPTARG
;;
*)
echo "error "
exit 7
;;
esac
done
[email protected]-unknown85879:~$ sh getopt.sh -d dd
is d
dd
[email protected]-unknown85879:~$ sh getopt.sh -b hello
is b
hello
6、shell的函数
几乎所有语言都会有函数,shell也不例外,下面看看函数的语法:
格式:
function functionname ()
{
body;
}
调用方式:直接函数名调用
functionname
示例1:我将之前的用于case语句的实例,改写成用函数实现看看
[email protected]-unknown85879:~$ cat test.sh
#!/bin/bash
function stop ()
{
echo "your chiose is stop ,stopping !"
}
function start ()
{
echo "your chiose is start,startting !"
}
function restart ()
{
echo "your chiose is restart,restartting !"
}
if [ "$1" = "stop" ];then
stop
elif [ "$1" = "start" ];then
start
elif [ "$1" = "restart" ];then
restart
else
echo "your input is error ,try again !"
fi
[email protected]-unknown85879:~$ sh test.sh
your input is error ,try again !
[email protected]-unknown85879:~$ sh test.sh stop
your chiose is stop ,stopping !
[email protected]-unknown85879:~$ sh test.sh start
your chiose is start,startting !
[email protected]-unknown85879:~$ sh test.sh restart
your chiose is restart,restartting !
[email protected]-unknown85879:~$
这里注意对比字符串时,if里面的变量要双引号括起来,否则会报错,== 和 =在这里是等价的。
四、shell的环境变量
1、环境变量有哪些,如何保存和生效?
(1)环境变量有很多,按不同的作用域分有系统环境变量如path,用户环境变量如用户自定义的家目录,或者命令别名,应用环境变量如jdk环境变量。
如何查看:直接输入 env
查看某个环境变量:如查看path: echo $PATH
(2)按作用时间来看有临时环境变量,有永久环境变量:
比如我们的$HOME是一个永久环境变量,我们要临时修改它,直接export 一下:
[email protected]-unknown85879:~$ echo $HOME ---修改前
/home/zhugeling
[email protected]-unknown85879:~$ export HOME=‘/home/tmp‘
[email protected]-unknown85879:/home/zhugeling$
[email protected]-unknown85879:/home/zhugeling$ echo $HOME ---修改后
/home/tmp
说明这种事临时生效,系统重启,或重新打开一个shell终端是会失效的。
环境变量永久生效的办法:直接修改配置文件或将修改保存到配置文件
(3)、常见环境变量的配置文件有哪些?
系统全局作用:
/etc/profile
/etc/profile.d/*.sh
/etc/bashrc
生效: source 路径
对当前用户起作用:
~/.bash_profile
~/..bashrc
生效: source 路径
对应用本身起作用的(不同应用配置文件名和路径不一样):
/etc/ssh/sshd_config
/etc/ssh/ssh_config
生效:一般是重启应用或reload
2、shell的ps1/ps2/ps3有什么用:
(1)ps1:
先来个例子看看是什么作用的
[email protected]-unknown85880:~/tmp$ export PS1=‘\t >‘
20:24:06 >
20:24:07 >
说明:从上例可以看到ps1可以通过export方式改变系统的终端提示符,ps1就是命令行提示符的环境变量。上面通过export改变环境变量的值,将显示结果改成时间而达到的效果。它还有更多其他参数如:
\a搜索 显示系统日期,格式:星期 日期
例:PS1="\d >" 结果:六 10月 24 >
\A 显示系统时间,格式:HH:MM
例:PS1="\A >" 结果:21:04 >
\t 显示系统时间,格式:HH:MM:SS (24小时制)
例:PS1="\t >" 结果:21:04:32 >
\T 显示系统时间,格式:HH:MM:SS (12小时制)
例:PS1="\T >" 结果:09:04:32 >
\h 显示主机名称(简称)
例:PS1="\h >" 结果:CentOS >
\H 显示主机名称(全称)
默认值是:[\[email protected]\h \W]$
刚刚只是临时修改,如果要长久生效怎么办?
放在个人家目录下的 .bashrc吧
如:
export PS1=’\t\h’
如果要全局生效呢?
我们来试试,我修改了/etc/profile的文件,后面追加 export PS1=’\t\h’,source之后,root用户立马生效,但是登录其他用户发现没效果。
排查发现用户下的.bashrc是有对PS1设置的:
if [ "$color_prompt" = yes ]; then
PS1=‘${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\[email protected]\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ ‘
else
PS1=‘${debian_chroot:+($debian_chroot)}\[email protected]\h:\w\$ ‘
fi
unset color_prompt force_color_prompt
经查资料,原来是登录读取配置文件的先后顺序也有关,最后读取的当然是最终起作用了:
/etc/profile ->.bash_profile -> .bashrc -> /etc/bashrc
那我们改 /etc/bashrc 试试:
[email protected]-unknown85880:~# source /etc/bash.bashrc
20:49:05newbie-unknown85880:
20:49:06newbie-unknown85880:
20:49:06newbie-unknown85880:
20:49:06newbie-unknown85880:tail -1 /etc/bash.bashrc
export PS1=‘\t\h:‘
果然如此。
Shell还有PS2,PS3,ps2是Shell的次提示符,PS3是Shell脚本中使用select时的提示符
举例:
默认显示如下:
[email protected]-unknown85881:~$ sh test.sh
1) mon
2) tue
3) wed
4) exit
#? 1
Monday
#? 2
Tuesday
#? 3
Wednesday
#? ^C
修改PS3=’\tmyshell’:
[email protected]-unknown85881:~$ export PS3=‘\tmysell:‘
[email protected]-unknown85881:~$ sh test.sh
1) mon
2) tue
3) wed
4) exit
\tmysell:1
Monday
\tmysell:2
Tuesday
\tmysell:
其他的生效顺序,长久生效配置跟ps1是一样的。
3、登录方式不一样对环境变量的影响:
有时候我们会碰到,用不同的用户去启动一个应用时会报错,除了文件权限不一样之外,通常还有另外一个原因就是不同用户的环境便令不一样。
(1)登录shell和非登shel:
登录shell:是通过账号密码登录进入shell的(或者通过”–login”选项生成的shel)
非登录shell:不需要账号密码,直接通过bash命令或者桌面右键打开的终端。
[email protected]-unknown85879:/etc/ssh# echo $$
26497
[email protected]-unknown85879:/etc/ssh# bash
[email protected]-unknown85879:/etc/ssh# echo $$ ---shell的进程ID跟之前不一样
30154
[email protected]-unknown85879:/etc/ssh# exit
exit
正常登录文件的读取调用关系:
执行/etc/profile中的命令,然后/etc/profile调用/etc/profile.d目录下的所有脚本;然后执行~/.bash_profile,~/.bash_profile调用~/.bashrc,最后~/.bashrc又调用/etc/bashrc
非登录shell:
执行~/.bashrc,~/.bashrc调用/etc/bashrc,然后调用/etc/profile.d/*下的所有脚本。
区别:非登录shell不会重新加载/etc/profile,而且顺序也不一样,如果你的环境变量设置是在/etc/profile和~/.bash_profile ,建议重新登录或source一下对应的配置文件。
登录方式:su user 和 su - user的区别:
su user :只是切换了用户,切换了权限,但是环境变量没变。
su - user : 切换了用户,切换了权限,也切换了环境变量
[email protected]-unknown85879:/home/zhugeling$ su root
Password:
[email protected]-unknown85879:/home/zhugeling# ---目录没换
[email protected]-unknown85879:/home/zhugeling$ su - root
Password:
[email protected]-unknown85879:~# ---目录换了
(2)交互式shell和非交互式shell:
我们把命令行终端这种输入一个命令,shell、去执行,然后输出结果,这种叫交互式shell,非交互式shell是指shell自己一直执行到执行完就退出shell的模式,脚本执行就是典型的非交互式shell。
我们可以通过echo $- 来判断当前是什么类型的shell:
[email protected]-unknown85879:/etc/ssh# echo $- --交互式
himBHs
[email protected]-unknown85879:/etc/ssh# cat test.sh
echo $-
[email protected]-unknown85879:/etc/ssh# sh test.sh ---非交互式
hB
在环境变量上的区别:
交互式shell:就是当前登录用户的环境变量(根据登录方式不同也会有区别)
非交互式shell:继承当前登录用户的环境变量,在此基础上shell可以在脚本里加载其他环境变量,如通过export PATH=’..’ 等
五、正则表达式和通配符的区别
(1)、作用对象和范围不一样:
作用对象:
通配符用于Linux的shell命令(如文件名相关操作),如常结合find ,cp,mv等命令使用
正字表达是是用于文本字符串或者标准输出里的内容的过滤和匹配
作用范围:
通配符必须在unix环境或类Unix环境中使用
正则表达式在很多语言中都支持,是一种标准,可以写在代码中,跨平台性好。
(2)解释器不一样:
通配符是Linux系统本身支持的,由shell去解析执行。
正则表达式在使用过程中有可能是shell去解析,也有可能是awk,perl等支持正则的命令去解析,就看使用方式是怎么用。
如:
[email protected]-unknown85879:/home/zhugeling$ ls -l logrotate.sh_* |grep "*" ---这里前面*号是通配符,后面*号只是一个*号
-rw-r--r-- 1 zhugeling zhugeling 1628 Feb 1 12:13 logrotate.sh_v*
[email protected]-unknown85879:/home/zhugeling$ ls -l logrotate.sh_* ---这里*号是通配符号
-rw-r--r-- 1 zhugeling zhugeling 1628 Feb 1 12:13 logrotate.sh_v*
-rw-r--r-- 1 zhugeling zhugeling 969 Jan 30 20:34 logrotate.sh_v1
-rw-r--r-- 1 zhugeling zhugeling 1940 Jan 31 11:20 logrotate.sh_v2
-rw-r--r-- 1 zhugeling zhugeling 1628 Jan 31 12:11 logrotate.sh_v3
[email protected]-unknown85879:/home/zhugeling$ ls -l logrotate.sh_* |grep ‘v*‘ --这里*号是正则修饰符
-rw-r--r-- 1 zhugeling zhugeling 1628 Feb 1 12:13 logrotate.sh_v*
-rw-r--r-- 1 zhugeling zhugeling 969 Jan 30 20:34 logrotate.sh_v1
-rw-r--r-- 1 zhugeling zhugeling 1940 Jan 31 11:20 logrotate.sh_v2
-rw-r--r-- 1 zhugeling zhugeling 1628 Jan 31 12:11 logrotate.sh_v3
ls -l logrotate.sh_* |grep ‘v*’ 中 起一个是由shell去解释执行的,而后面的是由grep 解释的,发现grep 后面用星号作为正则修饰符的话,记得前面不能为空,否则就不是正则里的修饰符作用了。
(3)符号用法含义不一样:
正则表达式支持的功能比较多,且符号的作用含义跟通配符很多是不一样的,比如:
$符号:
正则表示字符串的结尾
通配符中经常用来来引用变量。
*符号
正则里是修饰符,表示0个或多个,不能单独使用,例如 a* 表示0个a或者多个a。
通配符里表示的是任意字符,任意个,即匹配所有。
. 符号
正则里是匹配任意单个字符
通配符里没有这个含义,通配符用?来实现匹配任意单个字符的功能
[email protected]-unknown85879:/home/zhugeling$ find ./ -name "logrotate.sh_v?"
./logrotate.sh_v*
./logrotate.sh_v1
./logrotate.sh_v2
./logrotate.sh_v3
六、管道与重定向
(1)标准输入输出:
了解重定向首先要了解标准的输入输出是什么:
0: Standard Input (STDIN) 标准输入,如键盘输入
1: Standard Output (STDOUT) 标准输出,正确返回值,输出到前端
2: Standard Error Output (STDERR) 错误输出,输出到前端
(2)重定向
重定向就是将标准的输入或者输出重新指向到指定的文件或其他管道中。
“>” 重定向覆盖或新生成文件
如:1>文件名 可以将1省略,写成 >文件名
echo "hello" >test.txt
[email protected]-unknown85879:/home/zhugeling/tmp$ cat test.txt
hello
“>>” 重定向追加到指定文件中
echo "hellohhhh" >>test.txt
[email protected]-unknown85879:/home/zhugeling/tmp$ cat test.txt
hello
hellohhhh
错误输出重定向:
[email protected]-unknown85879:/home/zhugeling/tmp$ ppspsp 2>test.txt
[email protected]-unknown85879:/home/zhugeling/tmp$ cat test.txt
-bash: ppspsp: command not found
看下下面两个有什么区别:
pdkf 1>> test.txt 2>&1 将错误输出也输出到1标准输出通道中,继而输出到文件,是追加方式。
pdkf 1> test.txt 2>>&1 这种是错误的写法
cat test2.txt和cat> test2.txt的区别:
[email protected]-unknown85879:/home/zhugeling/tmp$ cat >test2.txt
lll
lsld
[email protected]-unknown85879:/home/zhugeling/tmp$ cat test2.txt
lll
lsld
输入重定向:
cat> test.txt<输出给test.txt
第一个EOF必须以重定向字符<<开始,第二个EOF必须顶格写,否则会报错
[email protected]-unknown85879:/home/zhugeling/tmp$ cat> test.txt<<eof
> haohsd
> aldwe
> eof
[email protected]-unknown85879:/home/zhugeling/tmp$ cat test.txt
haohsd
aldwe
(3)、管道命令:
-exec 使用时最后面一定要加;号表示结束,一般用反斜杠将;转义。
[email protected]-unknown85879:/home/zhugeling/tmp$ find ./ -name "test*"
./test.txt
./test2.txt
[email protected]-unknown85879:/home/zhugeling/tmp$ find ./ -name "test*" -exec cp {} /home/zhugeling/tmp/log/ \;
[email protected]-unknown85879:/home/zhugeling/tmp$ cd log/
[email protected]-unknown85879:/home/zhugeling/tmp/log$ ls test*
test2.txt test.txt
exec有个特点要注意:exec后面跟的是其他命令,当其他命令执行完之后,会退出当前shell,后面语句不执行,我在脚本测试是这样,命令行终端没测明白。
[email protected]-unknown85879:/home/zhugeling/tmp$ sh test.sh
hello mysql
hello oracle
[email protected]-unknown85879:/home/zhugeling/tmp$ cat test.sh
#!/bin/bash
echo "hello mysql"
exec echo " hello oracle"
echo "hello db2"
管道符号: |
command 1 | command 2 他的功能是把第一个命令command 1执行的结果作为command 2的输入传给command 2
[email protected]-unknown85879:/home/zhugeling/tmp$ ls -s
total 8
4 log 0 test2.txt 4 test.sh
[email protected]-unknown85879:/home/zhugeling/tmp$ ls -s|sort -nr
4 test.sh
4 log
total 8
0 test2.txt
xargs 管道命令
xargs 可以读入 stdin 的资料,并且以空格或换行作为分隔,将 stdin 的内容分隔成为 arguments 。 因为是以空格作为分隔,所以,如果有一些内容或者是其他意义的名词内含有空格的时候, xargs 可能就会误判了,如果需要处理特殊字符,需要使用-0参数进行处理
(1)、从文件中获取输入:
[email protected]-unknown85879:/home/zhugeling/tmp$ cat test.sh
#!/bin/bash
echo "hello mysql"
exec echo " hello oracle"
echo "hello db2"
[email protected]-unknown85879:/home/zhugeling/tmp$ xargs -a test.sh echo
#!/bin/bash echo hello mysql exec echo hello oracle echo hello db2
(2)将find的结果通过xargs重定向输出给ls -l
[email protected]-unknown85879:/home/zhugeling/tmp$ find ./ -name "test*"
./test2.txt
./test.sh
[email protected]-unknown85879:/home/zhugeling/tmp$ find ./ -name "test*" |xargs ls -l
-rw-r--r-- 1 zhugeling zhugeling 0 Feb 1 14:36 ./test2.txt
-rwxr--r-- 1 zhugeling zhugeling 79 Feb 1 15:03 ./test.sh
七、bash与shell的区别
shell是Bourne shell 是 UNIX 最初使用的 shell,而Linux 操作系统缺省的 shell 是Bourne Again shell,它是 Bourne shell 的扩展,简称 Bash,与 Bourne shell 完全向后兼容,他们的区别我根据以下几点做了比较:
可移植性:
bash的可移植性比shell要差一些,因为很多Linux版本都是在Unix上扩展出来的,那么其他shell也是在unix shell 上扩展出来的,扩展的shell一般都是向下兼容的。
功能使用:
在编程方面,shell是做的不错的,但是不支持命令补全,命令编辑,命令历史表等功能,而bash 支持。
原文地址:https://www.cnblogs.com/lifei02/p/9892512.html