一些基础脚本知识

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一些基础脚本知识相关的知识,希望对你有一定的参考价值。

编程基础:
程序:指令+数据
程序编程风格:
过程式:以指令为中心,数据服务于指令。 小软件过程,大软件对象。
对象式:以数据为中心,指令服务于数据
shell程序:提供了编程能力,解释执行
shell脚本基础:
shell脚本:
包含一些命令或声明,并符合一定格式的文本文件
格式要求:首行shebang机制
#!/bin/bash
#!/usr/bin/python
#!/usr/bin/perl

shell脚本的用途有:
自动化常用命令
执行系统化管理和故障排除
创建简单的应用程序
处理文本或文件
创建shell脚本
第一步:使用文本编辑器来创建文本文件
第一行必须包括shell声明序列:#!
 #!/bin/bash
 添加注释
 注释以#开头
第二步:运行脚本
给予执行权限,在命令行上指定脚本的绝对或相对路径
直接运行解释器,将脚本作为解释器程序的参数运行

脚本规范:
脚本代码开头约定:
1、第一行一般为调用使用的语言
2、程序名,避免更改文件名为无法找到正确的文件
3、版本号
4、更改后的时间
5、作者相关信息
6、该程序的作用,及注意事项
7、最后是各版本的更新简要说明

脚本的基本结构:
脚本的基本结构
#!SHEBANG
CONFIGURATON_VARIABLES
FUNCTION_DEFINITIONS
MAIN_CODE

shell脚本示例
#!/bin/bash
# ------------------------------------------
# Filename: hello.sh
# Revision: 1.1
# Date: 2017/06/01
# Author: wang
# Email: [email protected]
# Website: www.magedu.com
# Description: This is the first script
# ------------------------------------------
# Copyright: 2017 wang
# License: GPL
echo “hello world”
脚本调试
检测脚本中的语法错误
bash -n /path/to/some_script
调试执行
bash -x /path/to/some_script
bash -n 只能检查语法错误
变量
变量:命名的内存空间
 数据存储方式:
字符:
数值:×××,浮点型
变量:变量类型
    作用:
1、数据存储格式
2、参与的运算 
3、表示的数据范围
类型: 
字符
数值:×××、浮点型
加" "可以改变格式 如: echo="name"
变量:
强类型:变量不经过强制转换,它永远是这个数据类型,不允许隐式的类型转
换。一般定义变量时必须制动类型、参与运算必须符合类型要求;调用未声明
变量会产生错误
如 java,c#
弱类型:语言的运行时回隐形做数据类型转换。无须指定类型,默认均为字符型;
参与运算会自动进行隐式类型转换;变量无需事先定义可直接调用
如:bash不支持浮点数,php  可以用数字但是不能放在前面
变量命名法则:
1、不能使程序中的保留字:列如if,for
2、只能使用数字、字母及下划线,且不能以数字开头
3、见名知义
4、统一命名法则:骆峰命名法:把多个首字母大写,小驼峰:第一个首字母大写,
bash中变量的种类:
根据变量的生效范围等标准划分下面变量类型:
局部变量:生效范围为当前shell进程;对当前shell之外的其他shell进程,包括
当前shell的子shell进程均无效
环境变量:生效范围为当前shell进程及其子进程
本地变量:生效范围为当前shell进程中某代码片段,通常指函数
位置变量:$1,$2,...来表示,用于让脚本在脚本代码中调用通过命令行传递给它
的参数
特殊变量:$>,$0,[email protected],$#,$$
局部变量:
echo $$ 

echo $PPID:父子进程

局部变量只能在当前shell有效

在下级子进程变量不能往上传别的进程

全局变量:使用要加关键字 export :把当前变量转换环境变量
它允许往下传   父进程可以传给子进程   
bash 后台执行

declare -x 也可以生成所有环境变量

env也能显示环境变量

unset name 删除当前环境变量

set :本剧变量 全局变量都有

常量:固定值

readonly -p:显示常量

():用于一次性任务 执行一个小subsheell 不影响环境,
{}:和小括号有区别 

位置变量:能让脚本写死

$1 $2 $3
1 存的就是第一个字符串

10 个以上就得用{}
如:e‘cho "ALL args are {$10}"

scp :可以远程复制

scp.sh 

shift:从右往左挤掉

ping -c:指定网络拼一次
总结:
shell

变量:局部和环境    $1,[email protected] $*,$#,$0
set unset exprot declare -i -r -x env

环境变量:
变量声明、赋值:
export name=VALUE
declare -x name=VALUE
变量引用:$name,${name}
显示所有环境变量:
env
printenv
export
declare -x
删除变量:
unset name
环境变量:
bash内建的环境变量:
PATH
SHELL
UID
USER
HOME
PWD
SHLVL
LANG
MAIL
HOSTNAME
HISTSIZE
—:下划线

只读和位置变量:
只读变量:只能声明,但不能修改和删除
声明只读变量:
readonly name
declare -r name
查看只读变量:
readonly -p
位置变量:在脚本代码中调用命令行传递给脚本的参数
$1,$2,...:对应第1,第2等参数,shift [n]换位置
$0:命令本身
$*;传递给脚本的所有参数,全部参数合为一个字符串
[email protected]:传递给脚本的所有参数,每个参数为独立字符串
$#:传递给脚本的参数的个数
[email protected]$*只在被双引号抱起来的时候才会有差异
set -- 清空所有位置变量
退出状态:
进程使用退出状态来报告成功或失败
0代表成功,1 - 255代表失败
$?:变量保存最近的命令退出状态
列如:
ping -c1 -w1 hostdown &>/dev/null
echo$?

退出状态码:
bash自定义退出状态码
exit[n]:自定义退出状态码
注意:脚本中一旦遇到exit命令,脚本会立即终止;终止退出状态取决于exit命
令后面的数字
注意:如果未给脚本指定退出状态码,整个脚本的退出状态码取决于脚本中执行
的最后一条命令的状态码

算数运算:
bash中的算数运算:help let
+,-,*,%取模(取余),**(乘方)
实现算数运算:
1、let var=算数表达式
2、var=$[算数表达式]
3、var=$((算数表达式))
4、var=$(expr arg1 arg2 arg3...)
5、declare -i var =数值
6、echo  ‘算数表达式‘   | bc
乘法符号有些场景中需要转义,如*
bash有内建的随机数生成器:$RANDOM(0-32767)
echo $[$RANDOM%50】 :0-49之间随机数
赋值:
增强型赋值:
+=,-=,*=,/=,%=
let varOPERvare
列如:let count+=3
自加3后减值
自增,自减:
let var+=1
let var++
let var-=1
let var--
逻辑运算;
true,false
1,0
与:
1与1=1          & 并且 and
1与0=0          | 或者 or
0与1=0           cmd1 && cmd2     如果cmd1为假,cmd2不需要执行,反之cmd1为真,需要cmd2执行
0与0=0           cmd1 || cmd2如果为真,cmd2不需要执行,反之cmd1为假,需要cmd2执行
或:                  XOR 异或
1或1=1         0^1=1
1或0=1         0^0=0
0或1=1         1^0=1
0或0=0         1^1=0

逻辑运算:
非:!
!1=0
!0=1
短路运算:
短路与
第一个为0,结果必定为0
第一个为1,第二个必须要参与运算
短路或
第一个为1,结果必定为1
第一个为0,第二个必须要参与运算
异或:^
异或的两个值,相同为假,不必为真
条件测试;
判断某需求是否满足,需要由测试机制来实现
专用的测试表达式需要由测试命令辅助完成测试过程
评估布尔声明,以便用条件执行中
若真,泽返回0
若假,则返回1
测试命令:
testEXPRESSION
[ EXPRESSION]
[[ EXPRESSION]]
注意:EXPRESSUON前后必须有空白字符

条件性的执行操作符:
根据退出状态而定,命令可以有条件地运行
&&代表条件行的AN THEN
|| 代表条件行的OR ELSE
 例如:
grep -q no_such_user /etc/passwd || echo ‘No such user‘
No such user
ping -c1 -W2 station1 &> /dev/null > && echo "station1 is up" > || (echo ‘station1 is unreachable‘; exit 1)
station1 is up

test命令
? 长格式的例子:
test "$A" == "$B" && echo "Strings are equal"
test “$A” -eq “$B” && echo "Integers are equal"
? 简写格式的例子:
[ "$A" == "$B" ] && echo "Strings are equal"
[ "$A" -eq "$B" ] && echo "Integers are equal"

bash的数值测试
?-v VAR
变量VAR是否设置
?数值测试:
-gt  是否大于
-ge  是否大于等于
-eq  是否等于
-ne  是否不等于
-lt  是否小于
-le  是否小于等于

bash的字符串测试
?字符串测试:
==  是否等于
>  ascii码是否大于ascii码
<  是否小于
!=  是否不等于
=~  左侧字符串是否能够被右侧的PATTERN所匹配
注意: 此表达式一般用于[[ ]]中;扩展的正则表达式
-z "STRING“  字符串是否为空,空为真,不空为假
-n "STRING“  字符串是否不空,不空为真,空为假
? 注意:用于字符串比较时的用到的操作数都应该使用引号

Bash的文件测试
?存在性测试
-a FILE:同-e
-e FILE: 文件存在性测试,存在为真,否则为假
?存在性及类别测试
-b FILE:是否存在且为块设备文件
-c FILE:是否存在且为字符设备文件
-d FILE:是否存在且为目录文件
-f FILE:是否存在且为普通文件
-h FILE 或 -L FILE:存在且为符号链接文件
-p FILE:是否存在且为命名管道文件
-S FILE:是否存在且为套接字文件

Bash的文件权限测试
?文件权限测试:
-r FILE:是否存在且可读
-w FILE: 是否存在且可写
-x FILE: 是否存在且可执行
?文件特殊权限测试:
-u FILE:是否存在且拥有suid权限
-g FILE:是否存在且拥有sgid权限
-k FILE:是否存在且拥有sticky权限

Bash的文件属性测试
?文件大小测试:
-s FILE: 是否存在且非空
?文件是否打开:
-t fd: fd 文件描述符是否在某终端已经打开
-N FILE:文件自从上一次被读取之后是否被修改过
-O FILE:当前有效用户是否为文件属主
-G FILE:当前有效用户是否为文件属组

Bash的文件属性测试
?双目测试:
FILE1 -ef FILE2: FILE1是否是FILE2的硬链接
FILE1 -nt FILE2: FILE1是否新于FILE2(mtime)
FILE1 -ot FILE2: FILE1是否旧于FILE2

Bash的组合测试条件
?第一种方式:
COMMAND1 && COMMAND2 并且
COMMAND1 || COMMAND2 或者
! COMMAND 非
如:[[ -r FILE ]] && [[ -w FILE ]]
?第二种方式:
EXPRESSION1 -a EXPRESSION2 并且
EXPRESSION1 -o EXPRESSION2 或者
! EXPRESSION
必须使用测试命令进行
?示例:
[ -z “$HOSTNAME” -o $HOSTNAME "=="localhost.localdomain" ] && hostname www.magedu.com
[ -f /bin/cat -a -x /bin/cat ] && cat /etc/fstab

使用read命令来接受输入
?使用read来把输入值分配给一个或多个shell变量
-p 指定要显示的提示
-s 静默输入,一般用于密码
-n N 指定输入的字符长度N
-d  ‘字符’ 输入结束符
-t N TIMEOUT为N秒
read 从标准输入中读取值,给每个单词分配一个变量
所有剩余单词都被分配给最后一个变量
read -p “Enter a filename: “ FILE

bash如何展开命令行
?把命令行分成单个命令词
?展开别名
?展开大括号的声明({})
?展开波浪符声明(~)
?命令替换$() 和 ``)
?再次把命令行分成命令词
?展开文件通配(*、?、[abc]等等)
?准备I/0重导向(<、>)
?运行命令

防止扩展
?反斜线()会使随后的字符按原意解释
$ echo Your cost: $5.00
Your cost: $5.00
?加引号来防止扩展
? 单引号(’)防止所有扩展
? 双引号(”)也防止所有扩展,但是以下情况例外:
?$(美元符号) - 变量扩展
?`(反引号) - 命令替换
?(反斜线) - 禁止单个字符扩展
?!(叹号) - 历史命令替换

bash的配置文件
?按生效范围划分,存在两类:
?全局配置:
/etc/profile
/etc/profile.d/*.sh
/etc/bashrc
?个人配置:
~/.bash_profile
~/.bashrc
bashrc bash run command 
source 这种写法在当前脚本中运行
一般配置文件用source
变量普通脚本是不能支持别名的
10:16

shell登录两种方式
?交互式登录:
(1)直接通过终端输入账号密码登录
(2)使用“su - UserName” 切换的用户
执行顺序:/etc/profile --> /etc/profile.d/*.sh --> ~/.bash_profile -->
~/.bashrc --> /etc/bashrc
?非交互式登录:
(1)su UserName
(2)图形界面下打开的终端
(3)执行脚本
(4)任何其它的bash实例
执行顺序: ~/.bashrc --> /etc/bashrc --> /etc/profile.d/*.sh

Profile类
?按功能划分,存在两类:
profile类和bashrc类
?profile类:为交互式登录的shell提供配置
全局:/etc/profile, /etc/profile.d/*.sh
个人:~/.bash_profile
功用:
(1) 用于定义环境变量
(2) 运行命令或脚本

Bashrc类
?bashrc类:为非交互式和交互式登录的shell提供配置
全局:/etc/bashrc
个人:~/.bashrc
功用:
(1) 定义命令别名和函数
(2) 定义本地变量

编辑配置文件生效
?修改profile和bashrc文件后需生效
两种方法:
1重新启动shell进程
2 . 或source
例:
. ~/.bashrc

Bash 退出任务
?保存在~/.bash_logout文件中(用户)
?在退出登录shell时运行
?用于
? 创建自动备份
? 清除临时文件

$-变量
?h:hashall,打开这个选项后,Shell 会将命令所在的路径hash下来,避免每次
都要查询。通过set +h将h选项关闭
?i:interactive-comments,包含这个选项说明当前的 shell 是一个交互式的
shell。所谓的交互式shell,在脚本中,i选项是关闭的。
?m:monitor,打开监控模式,就可以通过Job control来控制进程的停止、继
续,后台或者前台执行等。
?B:braceexpand,大括号扩展
?H:history,H选项打开,可以展开历史列表中的命令,可以通过!感叹号来完
成,例如“!!”返回上最近的一个历史命令,“!n”返回第 n 个历史命令

read x y z  <<<  "i j k"
echo $.

9:42
   49
11:34

如何判断命令是否存在?
which mkisofs >& /dev/null
if  [ "$?"  != 0 ] ;  then
     echo "mkisofs Not Found"
     echo "yum install mkisofs"
fi

判断文件是否存在?
if  [ -f $2 ]; then
     echo "....."
     exit 1
fi

test(选项)
选项
-b<文件>:如果文件为一个块特殊文件,则为真;
-c<文件>:如果文件为一个字符特殊文件,则为真;
-d<文件>:如果文件为一个目录,则为真;
-e<文件>:如果文件存在,则为真;
-f<文件>:如果文件为一个普通文件,则为真;
-g<文件>:如果设置了文件的SGID位,则为真;
-G<文件>:如果文件存在且归该组所有,则为真;
-k<文件>:如果设置了文件的粘着位,则为真;
-O<文件>:如果文件存在并且归该用户所有,则为真;
-p<文件>:如果文件为一个命名管道,则为真;
-r<文件>:如果文件可读,则为真;
-s<文件>:如果文件的长度不为零,则为真;
-S<文件>:如果文件为一个套接字特殊文件,则为真;
-u<文件>:如果设置了文件的SUID位,则为真;
-w<文件>:如果文件可写,则为真;
-x<文件>:如果文件可执行,则为真。
实例
linux中shell编程中的test常见用法:

判断表达式

if test     #表达式为真
if test !   #表达式为假
test 表达式1 –a 表达式2     #两个表达式都为真
test 表达式1 –o 表达式2     #两个表达式有一个为真
test 表达式1 ! 表达式2       #条件求反
判断字符串

test –n 字符串    #字符串的长度非零
test –z 字符串    #字符串的长度是否为零
test 字符串1=字符串2       #字符串是否相等,若相等返回true
test 字符串1!=字符串2      #字符串是否不等,若不等反悔false
判断整数

test 整数1 -eq 整数2    #整数相等
test 整数1 -ge 整数2    #整数1大于等于整数2
test 整数1 -gt 整数2    #整数1大于整数2
test 整数1 -le 整数2    #整数1小于等于整数2
test 整数1 -lt 整数2    #整数1小于整数2
test 整数1 -ne 整数2    #整数1不等于整数2
判断文件

test File1 –ef File2    两个文件是否为同一个文件,可用于硬连接。主要判断两个文件是否指向同一个inode。
test File1 –nt File2    判断文件1是否比文件2新
test File1 –ot File2    判断文件1比是否文件2旧
test –b file   #文件是否块设备文件
test –c File   #文件并且是字符设备文件
test –d File   #文件并且是目录
test –e File   #文件是否存在 (常用)
test –f File   #文件是否为正规文件 (常用)
test –g File   #文件是否是设置了组id
test –G File   #文件属于的有效组ID
test –h File   #文件是否是一个符号链接(同-L)
test –k File   #文件是否设置了Sticky bit位
test –b File   #文件存在并且是块设备文件
test –L File   #文件是否是一个符号链接(同-h)
test –o File   #文件的属于有效用户ID
test –p File   #文件是一个命名管道
test –r File   #文件是否可读
test –s File   #文件是否是非空白文件
test –t FD     #文件描述符是在一个终端打开的
test –u File   #文件存在并且设置了它的set-user-id位
test –w File   #文件是否存在并可写
test –x File   #文件属否存在并可执行

expr用法

  expr命令一般用于整数值,但也可用于字符串。一般格式为:

  #expr argument operator argument

  expr也是一个手工命令行计数器。

  #$expr 10 + 10

  20

  #$expr 1500 + 900

  2500

  #$expr 30 / 3

  10

  #$expr 30 / 3 / 2
  5
  (注意运算符左右都有空格)
  使用乘号时,必须用反斜线屏蔽其特定含义。因为shell可能会误解显示星号的意义。
  #$expr 30 * 3
  90
  17.5.1 增量计数
  expr在循环中用于增量计算。首先,循环初始化为0,然后循环值加1,反引号的用法意
  即替代命令。最基本的一种是从(expr)命令接受输出并将之放入循环变量。
  $LOOP=0

  #$LOOP=`expr $LOOP + 1`

  17.5.2 数值测试
  可以用expr测试一个数。如果试图计算非整数,将返回错误。
  $rr=1.1
  #$expr $rr + 1
  #expr: non-numeric argument
  $rr=2
  $expr $rr + 1
  3
  (注意:这个例子与原文不同)
  这里需要将一个值赋予变量(不管其内容如何),进行数值运算,并将输出导入dev/null,
  然后测试最后命令状态,如果为0,证明这是一个数,其他则表明为非数值。
  $value=12
  #$expr $value + 10 > /dev/null 2>&1
  $echo $?
  0
  这是一个数。
  $value=hello
  #$expr $value + 10 > /dev/null 2>&1
  $echo $?
  2

  这是一个非数值字符。
  expr也可以返回其本身的退出状态,不幸的是返回值与系统最后退出命令刚好相反,成功返回1,任何其他值为无效或错误。下面的例子测试两个字符串是否相等,这里字符串为“hello”和“hello”。
  $value=hello
  $expr $value = "hello"
  1
  $echo $?
  0
  expr返回1。不要混淆了,这表明成功。现在检验其最后退出状态,返回0表示测试成功,
  “hello”确实等于“hello”。
  17.5.3 模式匹配

  expr也有模式匹配功能。可以使用expr通过指定冒号选项计算字符串中字符数。.*意即任何字符重复0次或多次。
  $value=accounts.doc
  $expr $value : ‘.*‘
  12
  在expr中可以使用字符串匹配操作,这里使用模式. d o c抽取文件附属名。
  $expr $value : ‘(.*).doc‘
  accounts

以上是关于一些基础脚本知识的主要内容,如果未能解决你的问题,请参考以下文章

php学习笔记——基础知识

JSP开发中的基础语法

常用python日期日志获取内容循环的代码片段

jQuery基础知识

Linux bash基础特性二

PHP基础知识:语法变量与数据类型