前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Linux基础(五)

Linux基础(五)

作者头像
企鹅号小编
发布2018-01-12 16:26:09
1.2K0
发布2018-01-12 16:26:09
举报
文章被收录于专栏:企鹅号快讯企鹅号快讯

一、shell编程基础

1、shell编程

程序=指令+数据

编程风格:

过程式:以指令为中心,数据服务于指令

对象式:以数据为中心,指令服务于数据

shell程序:提供了编程能力,解释能力

2、路径设置

export $PATH:/root

export $PATH:. shell脚本到哪儿都能执行(不建议)很危险

vim .bash_profile

生效:. .bash_profile

source .bash_profile

问题:当我创建一个shell文件之后,当移动着个文件后,发现他任然在找/root/bash(之前设置了PATH路径),原因是?

答:因为hash值的原因,外部命令第一次执行时搜索的路径会记录在内存的hash表中

hash查看一下,会发现有/root/first.sh

清除一下:hash -d first.sh

问题: 脚本执行,命令错误,继续执行

脚本执行,语法错误,终止执行

bash -n 语法检查,但不检查命令错误

bash -x 查看执行过程,跟踪调试

pstree :查看进程树 pstree -p

$$:可以查看当前进程id号

PS2 : 多行提示符

3、变量赋值:

name="String" #加入多行文件时加""会保留原格式(name=`cat /etc/issue` echo "$name")

cmd=hostname--> echo $cmd --> centos7.3.vincent

4、变量调用:

$ : $name

子:

vim par.sh

#!/bin/bash

name="par"

echo "par pid is $$"

echo "par.sh:name=$name"

/bin/bash son.sh /root/sun.sh . /root/sun.sh

echo "son.sh:name=$name"

vim son.sh

#!/bin/bash

export name

#name="son"

echo "son pid is $$"

echo "son.sh:name=$name"

结果:子进程的变量只在子进程中有效

从上面的例子中,我们能够得出:./ /bin/bash source三种执行方式的不同

./ 与 /bin/bash 都是新开进程,进行执行,此时本地变量不会被继承,不改变当前环境,通常用于执行脚本文件

source 与 . 则是将子进程放到父进程进行执行,将影响当前环境,常用于读取配置文件

5、bash中变量分类、

本地变量(普通变量):生效范围为当前shell,对当前shell之外的其他shell进程,包括当前shell的子进程均无效

环境变量:生效范围为当前shell进程及其子进程(作用范围:当前shell、子shell、子子shell)

局部变量:生效范围为当前shell进程中某代码片段

位置变量:$1,$2,...来表示,用于脚本代码中调用通过命令行参数传递给它的参数

特殊变量:$?,$0,$*,$@,$#,$$

(1)声明环境变量

export name=VALUE

declare -x name=VALUE

(2)查看环境变量

env

declare -x

printenv

export

(3)本地变量赋值

name = 'value'

(4)可以使用引用value

(1)可以是直接字符串:name = "root"

(2)变量引用:name="$USER"

(3)命令引用:name=`COMMAND`

(5)变量引用:$ $name

"":弱引用,其中的变量引用会被替换成变量名

'':强引用,其中的变量引用不会被替换成变量值,而保持原字符

(6)显示自己定义的所有变量

set :显示出所有的变量包括一些函数

(7)删除变量

unset 变量名,...

(8)显示上一条命令执行情况

echo $? :返回上一个执行的结果,通常0为正确,1为错误(这个值不是固定的,可自己指定1-255)

(9)只读变量和位置变量

只读变量:只能声明,但不能删除和修改( 进程的声明周期 )

声明:readonly name

declare -r name declare -ir name ( i表示数字 )

查看:readonly -p

例如:PI = 3.1415926

位置变量:在脚本代码中调用通过命令行传递给脚本的参数

$1,$2,$3,...对应第一,第二...参数,shift [n] 换位置 [ $10 ,$ ]

$0 :命令本身

$* :传递给脚本的所有参数,全部参数合为一个字符串( "string1 string2....")

$@ :传递给脚本的所有参数,每个参数为独立字符串 ( "string1" "string2" "string3" ... )

$# :传递给脚本的参数的个数

$@ $* :只有在被双引号引起来的时候才会有差异

说明:在编写脚本时,进来先判断

[ $# -lt 1 ] && echo "Usage:$0 arg1..." && exit 0

位置变量注意点:

当引用参数大于10个时,我们在用$10,$11这种做法就不行,会出现错误,此时需要使用 $,$,......

清空位置变量

set --

位置变量的扩展功能(执行一次,移动一位,只使用$1就好)

但我们在执行一个程序时,如何判断其是否执行完,我们可以通过shift来看看

shift N(N值很大,超过了给定变量的总数),如果执行完了,就会返回相应的错误代码

6、算术运算

查看bash中算术运算:help let

常用算术运算符:+、-、*、/、%、**(乘方)

算术运算实现:

1 let var=算术表达式

注意: let i=0 -> echo $? --->1

k=0 --> let k++ -->echo $? 1

k=0 --> let ++k -->echo $? 0

2 var=$[算术表达式]

3 var=$((算术运算表达式))

4 var=$(expr arg1 arg2 arg3...)

5 declare -i var = 数值

6 echo '算术表达式' bc

算术运算中注意事项

乘法符号有些场景中需要转义,如*

bash有内建的随机数生成器:$RANDOM(1-32767)

echo $[$RANDOM%50] :生成1-49之间随机数

7、逻辑运算

布尔值

true、false

1 0

见0为0

见1为1

异或

相同为0,不同为1

用于交换两数的值

短路

aa && bb aa为假则结束运算 (qq执行成功,则执行bb命令)

aa bb aa为真则结束运算 (aa命令失败,则执行bb命令)

实例:

1、判断用户存在否,在则返回用户名否则创建该用户

id $name &> echo $name is exist useradd $name

2、ping某主机,通则打印up否则down

ping -w1 -c1 172.18.0.1 &> /dev/null && echo "The machine is up" echo "The machie is down"

8、退出状态

进程使用退出状态来报告成功或失败

0 --> 代表成功

1-255 --> 代表失败

$? 该变量保存最近的命令退出状态

实例

$ ping -c1 -w1 hostname &> /dev/null-c:ping的次数 -w:几秒ping一次

$?

退出状态码

bash自定义退出状态码

exit [n]:自定义退出状态码

注意:脚本中一旦遇到exit命令,脚本会立即终止;终止退出状态取决于exit命令后面的数字

如果未给脚本指定主功能代码,整个脚本的退出状态码取决于脚本中执行的最后一条命令的状态码

9、条件测试

判断某需求是否满足,需要有测试机制来实现

专用的测试表达式需要由测试命令辅助完成测试过程

评估布尔声明,以便用在条件执行中

若真,则返回0

若假,则返回1

测试命令

test EXPRESSION

长格式:

$ test "$A" == "$B" && ehco " Strings are equal"

$ test "$A" -eq "$B" && echo "Integres are equal"

短格式:

$[ "$A" == "$B" ] && echo "Strings are equl"

$[ "$A" -eq "$B" ] && echo "Integres are equl"

空值或不赋值时是假 test $var && echo true

var="" test $var && echo true #结果都是假

var=" " test $var && echo true #结果为真

[ EXPRESSION ]

实例:判断一个文件是否存在,存在则退出

[ ! -e $1 ] && echo "The file not exist" && exit

[ -e $1 ] (echo "$1 is not exit " && exit) (这一条语句逻辑是不正确的,exit只是退出了子shell、子进程,并没有退出判断条件开启的shell)

改进:[ -e $1 ] { echo "$1 is not exit " ;exit;}(使用了匿名函数)

[[ EXPRESSION ]][[ ]]才支持正则表达式写法

注意:EXPRESION前后必须有空白字符,[ 是一个内部命令,[[ 是关键字

查帮助

help test

条件性的执行操作符

&& :代表条件性的AND THEN

:代表条件新的OR ELSE

实例:aa && bb cc :选择表达式

ping -c1 -w1 172.18.0.1 &> /dev/null && the host is up the host is down

read -p "Please enter a dirname:" fileuse

filename=${$fileuse:-"filename"}

=========================================================================================

变量赋值方式 变量y没有设置 变量y为空值 变量yshezho

x=$ x=新值 x=空 x=$y

x=$ x=新值 x=新值 x=$y

-------------------------------------------------------------------------------------

x=$ x=空 x=新值 x=新值

x=$ x=空 x=空 x=新值

--------------------------------------------------------------------------------------

x=$ x=新值 x=空 x=$y

y=新值 y值不变 y值不变

-------------------------------------------------------------------------------------

x=$ x=新值 x=新值 x=$y

y=新值 y=新值 y值不变

--------------------------------------------------------------------------------------

x=$ 新值输出到标准错误输出 x=空 x=$y

x=$ 新值输出到标准错误输出 新值输出到标准错误输出 x=$y

======================================================================================

10、比较运算符

(1)文件判断

-d filename:判断该文件是否存在,并且是否为目录文件

-e filename:判断文件是否存在(等价-a)d

-f filename:判断该文件是否存在,并且是否为普通文件

-b (你对软连接进行判断时,它判断的是软连接指向的文件( [ -b /dev/cdrom ] && exit 0)

-L 判断链接文件本身是什么文件( -h 存在且为符号链接文件)

-p 管道文件

-S 套接字文件

-s 大小为0

-r filename:...并且该文件是否拥有读权限(该权限是实际权限,而不是ll显示的权限,Acl权限)

-w

-x

-u filename :...是否拥有SUID权限【作用在二进制程序上,对目录无效】(passwd命令 chmod 4755添加suid权限)

-g (chmod 2755 )

-k (chmod o+t)

注意:在判断文件类型时,先判断软连接文件,在判断其他文件。软连接文件指向其真实的文件会先判断

(2)文件测试

文件大小测试:

-s file:是否存在且非空

文件是否打开

-t fd :fd表示文件描述符是否已经打开且与某终端相关

-N file:文件自动上一次被读取之后是否被修改过(即:修改时间是否比读的时间新)

-O file:当前有效用户是否为文件属主

-G file:当前有效用户是否为文件属组

双目测试

file1 -ef file2 :file1和file2是否指向同一个设备上的相同inode(判断硬链接)

file1 -nt file2 :file1 是否新于file2

file1 -ot file2 :file1是否旧于file2

(3)文件比较

file1 -nt file2:判断file1的修改时间是否比file2新

file1 -ot file2:...旧

file1 -ef file2:判断file1与file2的inode号是否相同(可理解为两文件是否为同一个文件,用于判断硬链接)

文件判断:

[[ "$sum" =~ ^.*\.sh$ ]] && echo $num is script $num is not script

(4)数字比较

-eq :判断是否相等

-ne :判断是否不相等

数字判断:

[[ "$sum" =~ ^-?[0-9]+$ ]] && echo $num is number $num is not number

(5)字符串比较

-z "string":判断字符串是否为空 ,空为真(变量加引号)

-n "string":判断字符串是否为非空,非空为真

test -n "$abc" && echo true

test -n && echo true #结果为真

== :判断两字符串是否相等

!= :判断两字符串是否不相等

> :ascii码1是否大于ascii码2

=~ :左侧字符串是否能够被右侧的PATTERN所匹配(左侧的字符串是否包含右侧pattern)

str=abc

[[ "$str" =~ "abc" ]] && echo true echo false

[[ $str =~ a.c ]] && echo true echo false(判断是否包含a,c不需要加引号)

注意:此表表达式一般用于 [[ ]]中;扩展的正则表达式

用于字符串比较时用到的操作数都应该使用引号

实例:

-z:True is string is empty

x=100 --> [ -z $x ] --> echo $? --> 1 : -z为空则真,

uset x--> [ -z $x ] --> echo $? --> 1 :-z非空则假,

-n:True in string is not empty

x=100 --> [ -n $x ] --> echo $? --> 1 :

uset x--> [ -n $x ] --> echo $? --> 1 :

x=100 --> [[ -n $x ]] --> echo $? --> 0 (使用[[ ]]才能看到正确结果)

(6)多重条件判断

判断1 -a 判断2 :逻辑与,1,2都成立,结果为真

判断1 -o 判断2 :逻辑或,1个成立结果为真

!判断 :逻辑非,原始的判断式取反

查看进程:

pstree -p

echo $$ :查看当前进程编号

echo $PPIP :查看父进程的进程号

判断一个文件是否以.txt结尾 ( ~ 表示后面跟正则表达式)

[[ $file =~ txt ]] && echo true

(7)组合测试表达式

第一种方法

command1 && command2 并且

command1 command2 或者

!command (!true 与 [ !true ]是不一样的)

第二种方式:

EXPRESSION1 -a EXPRESSION2 并且

EXPRESSION1 -o EXPRESSION2 或者

!EXPRESSION

必须使用测试命令进行

实例:

#[ -f /bin/bin/cat -a -x /bin/cat ] && cat /etc/fstab

如何判断输入的是数字

方法一

m=10

expr $m + 0

方法二

利用正则表达式

(8)总结:

1、那些括号的灵活使用

[表达式] test

( ) 开子进程

x=abc;echo $$;(echo $$ ;echo $x ;sleep 100; x=def ;echo $x );echo $x 【()开了子进程,sleep在子进程下再开进程执行】

结果:abc def abc

{ cmd1,cmd2,cmd3.... } 不开子shell。相当于顺序执行

x=abc;echo $$;;echo $x

结果:abc def def

11、I/O操作

1、read命令来接收键盘输入

使用read来把输入值分配给一个或多个shell变量;

-p 指定要显示的提示

-s 静默模式

-n N 指定输入的字符长度N

-d '字符' 输入结束符

-t N Timeout为n秒

read 从标准输入中读取值,给每个单词分配一个变量,所有剩余单词都被分配给最后一个变量

read -p "Enter a filename: " filename

实例

read n < /etc/issue--->echo $n ---->honstname is \n

read a b c echo $b yyy -->echo $c zzz

read m n l

12、bash中如何展开命令行

把命令行分成单个命令词

展开别名

展开大括号中的声明{}

展开波浪符声明~

命令替换$()和``

再次把命令行分成命令词

展开文件通配符(*、?、[abc]等)

准备I/O重定向()

运行命令

防止扩展

反斜线(\)会使随后的字符按愿意解释

$echo Your cost:\$5.00

Your cost:$5.00

加引号来防止扩展

单引号('')防止扩展

双引号("")也防止所有扩展,但以下情况例外:

$ ----> 变量扩展

``(反引号)->命令替换

\(反斜线)-->禁止单个字符扩展

!(叹号) -->历史命令替换

13、bash的配置文件

按生效范围划分,存在两类:

全局配置

/etc/profile

/etc/profile.d/*.sh

/etc/bashrc

个人配置:

~/.bash_profile

~/.bashrc */

14、shell登录两种方式

交互式登录:

(1)直接通过终端输入账号密码登录

(2)使用 "su - UserName "切换用户

执行顺序

/etc/profile --> /etc/profile.d/*.sh(登录就会执行,如果你想要配置的服务开机执行什么脚本就可以放在这里)*/ --> ~/.bash_profile (放环境变量)--> ~/.bahsrc (别名、本地变量)--> /etc/bashrc(靠后的生效)

非交互式登录

(1)su UserName

(2)图形界面下打开的终端

(3)执行脚本

执行顺序

~/.bashrc(别名和函数本地变量) --> /etc/bashrc --> /etc/profile.d/*.sh

.bash_profile:定义环境变量和开机启动项

source (.) scriptnaem 在当前shell执行*/

/bin/bash ./ 不开子进程执行

退出执行

/etc/bash_logout 退出的时候自动执行的文件,可在该文件中添加操作,当你退出时便会执行(rm -rf /app/* 当你退出时便会清空/app目录)*/

二、shell编程进阶

/etc/profile/vim.sh

本文来自企鹅号 - 微网天下媒体

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文来自企鹅号 - 微网天下媒体

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档