变量,元字符,流程判断if,while、for循环

2021/4/16 10:55:20

本文主要是介绍变量,元字符,流程判断if,while、for循环,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

一: shell编程介绍

1、一个shell脚本运行必须要拥有r和x权限; chamod u+x 1.txt

2、运行一个shell脚本的3个步骤:

(1)启动bash解释器

(2)bash把文件内容从硬盘读入内存

(3)bash把读入到内存的内容进行语法解释,控制操作系统执行shell代码

写脚本时候,应该规避好一些交互式的命令

3、运行脚本的有2中方法:

​ (1)交互式环境:每敲一个命令执行一次,但是不能永久保存

​ (2)文件内:一次全部执行,但是会永久保存

4、在当前界面运行脚本,不开启新进程

. 1.txt 在当前进程 或者 source 1.txt

bash 1.txt 开启了一个新进程

./ 1.txt 开启了新的一个进程

二:变量

1、变量的定义
变量需要先定义,后引用
per=36                                     #定义变量的时候,=两边不能有空格,否则报错       @@@
echo $per
echo ${per}G                               # 引用变量最好用这样的格式              @@@
2、变量名的使用规则
用字母,数字,下划线组成;不可用中文,以及一些既有的命令
3、变量值的类型
int整型       name=10
fault浮点型   name=3.14
str字符串     name="hello world"
4、特殊的符号                                                                  @@@@
"":双引号 
'':单引号的硬引用; 引号内的符号均无特殊意义
``:取里面命令的结果
$():取里面命令的结果,区别于上条的是,本条可以进行嵌套:
	$(命令 $(命令))
\:右斜杠

例子:
a=10
echo "$a"       #结果是10
echo '$a'       #结果是$10
echo "\$a"      #结果是$a                        #取消特殊字符的意义
echo $(+date %Y-%m-%y).txt
5、变量的作用域(生效范围)
 (1)全局变量:定义的变量只在该进程有效
 例子:
 per=36
 vim 1.txt (echo "$per")
 echo "$per"                           #有结果
 bash 1.txt                            #没有结果
 source 1.txt                          #有结果
 export per ; bash 1.txt               #有结果    (继承了per的结果给子进程,父进程看不到)  @@@@
   export的是遗传,子子孙孙进程都可以看待;但是子进程开启的变量,父进程不可以引用;
  
  
 (2)变量先从局部变量找,没有了再从父辈遗传的找,再从环境变量里找
 	
 (3)添加环境变量                                             #登录时候就自动启动
 	 * 对/root 临时添加环境变量           PATH=$PATH:/root          
 	 * 对/root 永久添加环境变量,并给到所有的子进程
 	 	vim /etc/profile  
 	 	   PATH=$PATH:/root
 	 	   export PATH
     env  查看所有的环境变量
     set  查看所有的变量,临时的也可以看到
 
  (4)删除变量
   unset per         

三:元字符(一些特殊符号)

元字符是被shell解释器解释,而正则表达式是被命令解释

1、{}、[]和!的应用:
touch {1..5}.txt
touch {a..e}.txt
ls [0-9].txt
ls [!0-9].txt
2、变量间的运算
  
 (1)整型和浮点型的运算
  ***expr 变量间不做什么的情况下只是整型int的运算
     $a + $b               特别注意中间的空格                                      @@@@@ 
 			c=`expr $a + $b`
     expr 支持 + - / % 除的话取整数,%为取余                                        @@@@@
     乘法是:expr 5 \* 3                                                         @@@@@
  ***bc
  	echo " 3.14 < 3.16 " | bc    
  	
 (2)let x++  等于在原来变量上加1不支持多加  没有此变量时候默认就为0
    a=10;  echo `expr $a + 1 `
 (3)&
   1个&放在命令的结尾表示后台运行
   2个&&放在2个命令之间,表示并且的意思;只有左边的命令成功的情况下才可以运行右边的命令
   &> 无论结果是否正确都重定向
 (4)|| 或者的意思
   wssfsf || ls     左边命令错误时,右边命令才运行; 也就是要不左边成立,要不右边成立
   ls || pwd        此时只运行ls命令
 (5);
   不管命令是否正确都会运行
   asfg ; pwd
 (6)()
   *取命令的结果:echo $(expr $a + $b)
   *嵌套取命令结果,或者进行运算:$(命令 $(命令)) 
    > >=  < <=  
    ==(等于)
    !=(不等于)
    &&(and)
    ||(or)
    例子:
        x=100   
        (( $x == 100 )) ; echo $?                                 #结果是1
        (( $x != 100 || 100 >= 10 )) ; echo $?                    #结果是0
    
 (7)[]  类似于test命令
 *test
   test $x -eq 5 ; echo $?
 *[]
   *进行整型运算:echo $[10 + 2]
   *进程过滤时候:ps -aux | grep [p]ing   去掉这个命令执行时候的进程
   *判断字符值是否相同;例子如下
   		name="egon" ; [ $name = "egon" ]
   		echo $?     #结果为0是真,结果为1是假的
   	 **小脚本(用户登录程序:要求只有用户名和密码对输出ok,其他ng):
   	   [root@local-test var]# cat 1.txt 
         #!/bin/bash
         read -p "yourname:" name
         read -p "passwd:" passwd
         [ $name = "zzyy" ] && [ $passwd = 123 ] && echo ok || echo NG
   *判断数字值是否相同;例子如下                                                     @@@@@
        *判断数字值相等:[ 10 -eq 10 ] && echo $?     结果是0
        *判断数字值大于:[ 10 -gt 8 ] && echo $?      结果是0
        *判断数字值大于等于:[ 10 -ge 12] ; echo $?    结果是1
        *判断数字值小于:[ 10 -lt 8 ] ; echo $?       结果是0
        *判断数字值小于等于:[ 10 -le 12] ; echo $?    结果是1
        *判断数字值不等于:[ 10 -ne 12] ; echo $?    结果是0
        *判断是否有一般文件:[ -f /root/2.txt ] ; echo $?    判断是否有这个普通文件2.txt
        *判断是否有这个文件:[ -e /root/2.txt ] ; echo #?    判断是否有这个文件2.txt
        *
  (8)? 指定一个字符
    ls ?.txt ; ls ??txt
    查找所有a到Z的文件  ls /etc/[a-Z].txt 
  (9) : 结果永远为真
      : ; echo $?    #结果是0
      
总结:
;   不管左右的命令是否成功都运行,错误就报错
&&  只有左边的成功时,右边的才会运行
||  或者左边的运行。或者右边的运行
3、如何进行小数的运算
 (1)yum install bc -y
 (2)echo $(echo "scale=2; 3/10" | bc  | cut -d '.' -f2 )%                        @@@@@
         结果:30%
     scale=2取小数点两位,后执行命令3/10,后bc做小数,后以.分割取出来点后的2位数字
     echo " 3.14 < 3.16 " | bc   
4、awk和bc的小例子
a=free | awk 'NR==2{print $NF}'      #拿出实际使用的内存    awk必须是单引号
b=free | awk 'NR==2{print $2}'       #总的内存
echo $(echo "scale=2; $a / $b " | bc | cut -d '.' -f2)%   #计算出%比
echo `echo "scale=2; $a / $b " |bc | cut -d "." -f2 `%
写脚本的时候注意事项:
对数据的增改删的时候需要
(1)set -o errexit      脚本有错误的时候不运行退出
     [root@local-test ~]# cat 1.txt 
        #!/bin/bash
        set -o errexit

        echo 111
        echo 222
        echo 333
        afsdfgdg
        echo 444
     [root@local-test ~]# bash 1.txt
        111
        222
        333
        1.txt: line 7: afsdfgdg: command not found  
     
     
(2)set -o nounset      只要变量不存在就退出   echo $yyy  yyy之前不被定义

(3)set -o pippefail    addsv| echo 123
egon--元字符总结

1、`` 与$():取命令的结果
    [root@localhost ~]# echo `pwd`
    /root
    [root@localhost ~]# echo $(pwd)
    /root
    ​
    不一样的地方在于$()可以嵌套,而``不能嵌套
    [root@localhost ~]# echo $(ls $(pwd))
    ​
    # 练习
    [root@aliyun test]# touch $(date +%F)_bak.tar.gz
    [root@aliyun test]# ls
    2020-08-24_bak.tar.gz

2、~家目录
3、.与..
4、!调用历史命令、取反
    # 1、调用历史命令
    [root@egon ~]# !1066
    [root@egon ~]# !ls # 匹配最近的一次历史命令
    ​
    # 2、取反1:对命令的结果取反
    [root@egon ~]# ! pwd
    /root
    [root@egon ~]# echo $?
    1
    ​
    # 3、取反2:效果与^雷同
    [root@localhost ~]# touch /test/{1.txt,2.txt,a.txt,aaa_bbb.txt}
    [root@localhost ~]# find /test ! -name 1.txt
    /test
    /test/2.txt
    /test/a.txt
    /test/aaa_bbb.txt
    ​
    [root@localhost ~]# ls /test/[!0-9].txt # .txt前只有一个字符,但是非数字
    /test/a.txt
    [root@localhost ~]# ls /test/[^0-9].txt # .txt前只有一个字符,但是非数字
    /test/a.txt
    ​
    [root@aliyun test]# ls -a /etc/skel/.[!.]*
5、@无特殊意义
6、#注释
7、$取变量值
(1)[root@localhost ~]# x=1
    [root@localhost ~]# echo $x
(2)%、-、+运算符,注意%可以与jobs配合“kill %工作号”杀后台进程。-减号还有区间及cd -回到上一级的意思
    # 数学运算
    # 1、bc是比较常用的linux计算工具了,而且支持浮点运算:
    [root@localhost ~]# res=`echo 1+1 | bc`
    [root@localhost ~]# res=`echo 1.2+1.3|bc`
     [root@localhost ~]# res=`echo "scale=2;5.0/3.0"|bc`
    [root@localhost ~]# echo $res
    2 取余
    [root@localhost ~]# res=`echo 10 % 3 | bc`
    [root@localhost ~]# echo $res
    [root@localhost ~]# res=`echo 5.0+3.0|bc`
    [root@localhost ~]# echo $res
    3、expr不支持浮点数计算。而且要注意数字与运算符中的空格
    [root@localhost ~]# res=`expr 5 / 3` # 不支持浮点计算
    [root@localhost ~]# echo $res
    [root@localhost ~]# res=`expr 1+1` # 注意:要有空格
    [root@localhost ~]# echo $res
    [root@localhost ~]# res=`expr 1 + 1`
    [root@localhost ~]# echo $res
    [root@localhost ~]# res=`expr 5 \* 3` # 在expr中*号要转义才能用,否则报语法错
    4、$(()) 同expr,不支持浮点数运算
    [root@localhost ~]# echo $((1+1))
    [root@localhost ~]# echo $((1.0+2.0))
    -bash: 1.0+2.0: 语法错误: 无效的算术运算符 (错误符号是 ".0+2.0")

    5、$[]同expr以及$(()),不支持浮点运算
    [root@localhost ~]# x=1
    [root@localhost ~]# echo $[$x+1]
    6、let 不支持浮点数运算,而且不支持直接输出,只能赋值
    [root@localhost ~]# let res=1+1
    [root@localhost ~]# echo $res
    2
    [root@localhost ~]#
    [root@localhost ~]# let res=50/5
    [root@localhost ~]# echo $res
    10
    [root@localhost ~]# let c=1.3*3
    -bash: let: c=1.3*3: 语法错误: 无效的算术运算符 (错误符号是 ".3*3"
    [root@aliyun test]# x=1
    [root@aliyun test]# let x+=10
    [root@aliyun test]# echo $x
    11
8、^同!一样
9、&后台运行
    [root@localhost home]# echo "hello";sleep 3;echo "world" &
    && 两个命令之间,前面那个运行成功后面才运行
10、*任意多个字符
    [root@localhost ~]# touch 1.txt 2.txt aa.txt aaa.txt
    [root@localhost ~]# rm -rf *.txt
    [root@localhost ~]# touch 1.txt 2.txt aa.txt aaa.txt a1c.txt
    [root@localhost ~]# ls *.txt
    1.txt 2.txt a1c.txt aaa.txt aa.txt
11、()在子shell中执行
    [root@localhost ~]# (x=1)
    [root@localhost ~]# echo $x
    应用
    [root@localhost ~]# (umask 066;touch a.txt) # umask的设置只在子shell中有效
    [root@localhost ~]# ll a.txt
    -rw-------. 1 root root 0 8月 13 15:22 a.txt
    [root@localhost ~]# touch b.txt
    [root@localhost ~]# ll b.txt
    -rw-r--r--. 1 root root 0 8月 13 15:23 b.txt
    10、_下划线:无特殊意义,可以用于名字的声明
    [root@localhost ~]# tar -czvf `date +%F_%H:%M:%S`_bak.tar.gz /etc/
    11、=赋值,==判断相等性
    [root@localhost ~]# [ 1 == 1 ] # 条件1 == 1的左右两边必须有空格
    [root@localhost ~]# echo $? # 判断上一条命令的结果是否为真,0=》true
    0
12、|管道:把一个进程的处理结果传递给另外一个进程
    [root@localhost ~]# ps aux | grep python
    |管道命令的作用,是将左侧命令的标准输出转换为标准输入,提供给右侧命令作为参数。但是,大多数命令都不接受标准输入作为参数,只能直接在命令行输入参数,这导致无法用管道命令传递参数。比如echo命令就不接受管道传参。
    $ echo "hello world" | echo
    xargs命令的作用,是将标准输入转为命令行参数,例如
    $ echo "hello world" | xargs echo
    hello world
    [root@localhost ~]# find /home/ -type d -name "test*" |xargs ls
    1.txt 2.txt 3.txt
    [root@localhost ~]# ls /home/test
    1.txt 2.txt 3.txt
13、\转义特殊字符
    [root@localhost ~]# mkdir a\ b.txt # 虽然可以,但不推荐
    [root@localhost ~]# ll
    总用量 0
    drwxr-xr-x. 2 root root 6 8月 13 15:35 a b.txt

    ​
    [root@localhost ~]# echo $RMB # 默认会当成变量
    ​
    [root@localhost ~]# echo '$RMB' # 取消特殊意义
    $RMB
    [root@localhost ~]# echo \$RMB # 取消特殊意义
    $RMB
14、[]条件测试,后续会详细介绍
    [root@localhost ~]# name="egon"
    [root@localhost ~]# [ $name == "egon" ];echo $?
    0
    [root@localhost ~]# name="adf"
    [root@localhost ~]# [ $name == "egon" ];echo $?
    1
    ​
    [root@localhost ~]# [ -d /test ];echo $?
    0
    [root@localhost ~]#
15、引号
    '' 强引用(在单引号中都视为普通字符)
    " " 弱引用 (在双引号中保留变量)
    ​
    [root@localhost ~]# x=111
    [root@localhost ~]# echo "$x"
    111
    [root@localhost ~]# echo '$x'
    $x
    [roo
16、;与&&与||连接多条命令
    [root@localhost home]# gagaga;ls # 不论前一条命令运行成功与否,都会执行后续命令
    bash: gagaga: 未找到命令...
    egon
    [root@localhost home]# gagaga && ls # 只有前一条命令执行成功,才会执行后续命令
    bash: gagaga: 未找到命令...

    [root@localhost home]# ls /test || mkdir /test # 前一条命令执行不成功才会执行后续命令
    0.txt 1.txt 2.txt 3.txt 4.txt 5.txt 6.txt 7.txt 8.txt 9.txt
17、:空命令,真值
    [root@egon ~]# :
    [root@egon ~]# echo $?
    0
18、/路径分隔符
19、{}循环列表
    [root@localhost home]# touch /test/{0..9}.txt
    [root@localhost home]# ls /test/
    0.txt 1.txt 2.txt 3.txt 4.txt 5.txt 6.txt 7.txt 8.txt 9.txt
    ​
    [root@localhost ~]# touch {1..3}{a..d}.txt
    [root@localhost ~]# ls
    1a.txt 1b.txt 1c.txt 1d.txt 2a.txt 2b.txt 2c.txt 2d.txt 3a.txt 3b.txt 3c.txt 3d.txt
    ​
    [root@egon ~]# x=100
    [root@egon ~]# echo ${x}% # 控制变量名的范围
    100%
    [root@egon ~]#
    [root@egon ~]# echo $xrmb
    ​
    [root@egon ~]# echo ${x}rmb
    100rmb
20、重定向
    > >> 输出重定向
    < << 输入重定向
    ​
    > 覆盖 >> 追加
    [root@localhost home]# cat >> a.txt << EOF
    > 111
    > 222
    > 333
    > EOF
    ​
    0标准输入、1标准正确输出、2标准错误输出,&标准正确和错误输出
    [root@localhost home]# pwd 1>a.txt
    [root@localhost home]# cat a.txt
    /home
    [root@localhost home]# gagag 2>a.txt
    [root@localhost home]# cat a.txt
    bash: gagag: 未找到命令...
    [root@localhost home]# gagaga &>/dev/null
    ​
    < << 输入重定向
    [root@localhost ~]# mysql -uroot -p123 < bbs.sql
    [root@localhost home]# grep root < /etc/passwd
    root:x:0:0:root:/root:/bin/bash
    operator:x:11:0:operator:/root:/sbin/nologin
    ​
    [root@localhost home]# dd if=/dev/zero of=/a.txt bs=1M count=10
    记录了10+0 的读入
    记录了10+0 的写出
    10485760字节(10 MB)已复制,0.024387 秒,430 MB/秒
    [root@localhost home]# dd </dev/zero >/b.txt bs=1M count=10
    记录了10+0 的读入
    记录了10+0 的写出
    10485760字节(10 MB)已复制,0.0202365 秒,518 MB/秒
    ​
    [root@localhost home]# ll /a.txt
    -rw-r--r--. 1 root root 10485760 8月 13 16:02 /a.txt
    [root@localhost home]# ll /b.txt
    -rw-r--r--. 1 root root 10485760 8月 13 16:03 /b.txt
21、?任意一个字符
    [root@localhost ~]# ls ??.txt
    aa.txt
    [root@localhost ~]# ls a?c.txt
    a1c.txt
    [root@localhost ~]# rm -rf *.txt
    22、范围中的任意一个字符 [12] [ac] [a-z] [0-9]
    [root@localhost ~]# touch a1c a2c axc aXc axd
    [root@localhost ~]# ls a?c
    a1c a2c axc aXc
    [root@localhost ~]# ls a[1x]c
    a1c axc
    [root@localhost ~]# ls a[a-z]c
    axc aXc
    [root@localhost ~]# ls a[A-Z]c # 不区分大小写
    axc aXc
    [root@localhost ~]# ls a[x]c
    axc
    [root@localhost ~]# ls a[X]c
    aXc
    [root@localhost ~]# ls a[0-9]c
    a1c a2c
    [root@localhost ~]# ls /dev/sd[a-z]*
    /dev/sda /dev/sda1 /dev/sda2 /dev/sda3 /dev/sdb1

三:流程控制之if判断

if的语法:
什么是if判断,为什么要用?
根据条件的真假来决定去做什么事情,要用是因为要让计算机代替人去做判断
1. 语法
 ***完整语法
	if 条件 ; then            # 如果条件是命令,一般把它丢到空里/dev/null
		代码1                 #如果条件1成立下面的elif不允许
		代码2 
	elif 条件 ; then          #如果条件1不成立,本条件运行
		代码1
		代码2
	elif 条件 ; then
		代码1
		代码2
	else
		代码1
		代码2
	fi                                           #if的反过来
	
 ***单分支语法
    if 条件 ; then
		代码1
		代码2
	fi
	
 ***单分支语法
    if 条件 ; then
		代码1
		代码2
	else
		代码1
		代码2
	fi      
    
 判断成绩的小例子:
 #!/bin/bash
read -p "your score:" score
if [ $score -gt 90 ] ;then
        echo "excellent"
elif [ $score -ge 60 ] ; then
        echo "good"
else
        echo "bad"
fi

四:循环

while循环
* true和:表示为真;开始和结束以do和done为准;结束循环可以是自然结束和break
命令格式:
while 条件
do
命令1
命令2
done

(1)脚本中的运行
登录的小例子:
#!/bin/bash
while :
do
	read -p "yourname:" name
	read -p "passwd:" passwd
	if [ $name = "zz" ] && [ $passwd = 123 ] ; then
		echo "login ok"
		break
	else
		echo "fluse"
	fi
done

打印10以内的数字:
#!/bin/bash
count=0                                        #中间不能有空格
while [ $count -le 10 ]
do
        echo $count
        (( count ++ ))
done


(2)在命令行中写入一行:
while 条件 ; do 命令1 ;命令2 ; done        实时显示一些状态
while true ; do ifconfig; sleep 0.5;clear; done     clear就是清屏
for 循环应用
for循环在固定循环次数的情况下优势强


#!/bin/bash
for i in `seq 0 3`
do
    if [ $i -gt 2 ]; then

        break
    fi
    echo $i
    
备注:seq 0 5 和{0..5} 是一个效果;都是0 1 2 3 4 5

ping一个段内的所有网址,看是否ping通
#!/bin/bash
for i in {2..100}
do
(ping -c1 192.168.15.$i &>/dev/null
if [ $? -eq 0 ]; then
	echo "192.168.15.$i up"
else 
	echo "192.168.15.$i down"
fi) &
done

备注:在命令后加上&,是使其在后台运行,能很大程度的提升运行速度

批量修改文件名

for name in ls *.txt;do mv $name ${name%.txt}.log;done

rename log txt *



这篇关于变量,元字符,流程判断if,while、for循环的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程