shell的特性之十:输入输出重定向和管道
文件描述符(句柄)file descriptor ,FD
是内核用来追踪现在文件的
INPUT:标准输入,stdin,0
OUTPUT:标准输出,stdout,1
标准错误输出:stderr,2
I/O重定向:
<,<<:输入重定向
<:输入重定向
<<:此处创建文件,常用于在脚本中创建文件或生成菜单
<< EOF EOF 此处生成文件
>,>>:输出重定向 !
>:覆盖输出,
>>:追加输出
set -C:禁止覆盖重定向至已经存在的文件
set +C:关闭上述特性:
>|:在-C 特性下,强制使用覆盖重定向
/dev/null:bit bucket 位桶
错误重定向:2>,2>>,会输出正确信息
2>:覆盖
2>>:追加
同时重定标准输出和错误输出:
命令 > /path/to/outfile 2>/path/to/errfile
命令 &> /path/to/somefile
命令 > /path/to/somefile 2>&1
管道:
Linux:
使用目的单一的小程序
组合小程序完成复杂的任务
command1 | commadn2 | command3
分叉输出:tee,命令不会处理,会送到下一个管道
bash中的算术运算:
declare
-i:整形变量
-x: 环境变量,类似于export
let:
let varName=算术表达式
varName=$[算术表达式]
varName=$((算术表达式))
varName=`expr 变量1 + 变量2 `
除法运算有余数被省略(圆整)
操作符:+,—,*,/,%(余数)
+=,-=,*=,/=,%=
let totalWeight+=2
totalWeight= $[$totalWeight+2]
id++,id--,每次都+1
***bash的单步执行:
bash -x /path/to/script***
知识点:位置参数
$0:脚本自身
$1:脚本的第一个参数
$2:
....
特殊变量:
$#:显示所有位置参数的个数
$*,$@:引用所有的位置参数
交互式脚本
read -p 交互
给变量以默认值
varName=${varName:-value}
如果varName不空,则返回varName的值;否侧,则返回value
如果varName不空,则其值不变;否则,varName会使用value作为其值
文本处理工具之grep egrep 和fgrep
文本搜索工具,根据用户指定的文本模式对目标文件进行逐行搜索,显示能够模式所匹配到的行
格式:
grep [options]’PATTERN’ file,…
--color=auto
-v:反向匹配,显示不能被模式匹配到的行
-o:仅匹配被模式匹配到的字串,而非整行
-i:不区分大小写,ignore-case
-E:支持扩展
-A #:还显示模式下面的一行
-B #:还显示模式上面的一行
-C #:前后各显示一行
egrep:
使用扩展正则表达式来构建模式,相当于 grep -E
元字符:
字符匹配:
.:任意单个字符
[]:指定范围内的任意单个字符
[^]:指定范围外的任意单个字符
次数匹配
*:匹配器前面的字符任意次
?:匹配器前面的字符0或1次
+:匹配其前面字符至少一次
{m}:匹配其前面字符m次
{m,n}:至少m次,至多n次
{m,}:至少m次
{0,n}:只读n次
分组:
():分组
|:或者,ac|bc ac或者bc
fgrep:fast
不解析正则表达式
正则表达式:是一类字符所书写出的模式
元字符:
不表示字符本身的意义,用于额外功能性的秒速
基本正则表达式和扩展正则表达式
基本正则表达式的元字符:
grep -E
字符匹配:
. : 任意单个字符
次数匹配:用来指定匹配其前面的字符的次数
*:任意次
.*:匹配任意长度的任意字符
\?:前面字符出现0次或者1次的
\{m\}:匹配m次
\{m,n\}:至少m次,至多n次
\{m,\}:至少m次
\{0,n}:至多n次
贪婪模式:尽可能的长的去匹配字符
位置锚定:用于指定字符出现的位置
^:锚定行首
^Char
$:锚定行尾
grepchar$
^$:空白行
单词的位置锚定
\<char :锚定词首,\b
char\> : 锚定词尾,char\b
分组:
n\(\)
\(ab\)*xy
引用:
\1:后向引用,引用前面的第一个左括号以及与之对应的右括号中的模式匹配到的内容,意思是说前面出现一次,在\1这也要出现一次
bash编程之条件判断
目的:判定后续操作的前提条件是否满足
条件判断的常用判断类型:
整数测试:比较两个数谁大谁小
字符测试:比较两个字符是否相等
文件测试:判断文件的存在和文件类型
$?: 执行状态码
0:正确
1-255:错误
布尔值:
真 假
逻辑运算:
与运算:
真 && 真 = 真(0)
真 && 假 = 假
假 && 真 = 假
假 && 假 = 假
或运算:
真 || 真 = 真(0)
真 || 假 = 真
假 || 真 = 真
假 || 假 = 假
非运算:
!真 = 假
!假 = 真
bash中如何做测试
test 表达式
[ 测试表达式 ]
[[ 测试表达式 ]]
bash中条件判断使用if:
单分支:
if 条件; then
分支1;
fi
双分支:
if 条件; then
分支1;
else
分支2;
fi
多分支:
if 条件; then
分支1;
elif 条件2; then
分支2;
elif 条件3; then
分支3;
...
else
分支n;
fi
只要命令用作条件,就表示引用的是其状态结果(即执行成功与否),而非命令的输出结果,因此,不能使用命令替换符.
bash编程之:整数测试
二元测试:
num1 操作符 num2
-eq 等于
-ne 不等于
-le:小于等于
-ge:大于等于
-lt:小于
-gt:大于
练习
1、显示/proc/meminfo文件中的以大小写s的开头的行
grep -i "^s" /proc/meminfo
2、取出默认shell为非bash的用户
grep -v "bash$" /etc/passwd | cut -d: -f1
3、取出默认shell为bash的且其ID号最大的用户
grep "bash$" /etc/passwd |cut -d: -f1|sort -n -t: -k3|tail -1
4、显示/etc/rc.d/rc.sysinit文件中,以#开头,后面跟至少一个空白字符,而后又有至少一个非空白字符的行
grep "^#[[:space:]]\{1,\}[^[:space:]]\{1,\}" /etc/rc.d/rc.sysinit
5、显示/boot/grub/grub.conf中以至少一个空白字符的行
grep "^[[:space:]]\{1,\}" /boot/grub/grub.conf
6、查出/etc/passwd中一位数或两位数
grep --color=auto "\<[0-9]\{1,2\}\>" /etc/passwd
7、找出ifconfig命令结果中的1到255之间的整数
ifconfig |grep -E --color=auto "\<([1-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\>"
8、查看当前系统上root用户的所有信息
grep “\<root\>”/etc/passwd
9、找出netstat -tan命令执行的结果中以“LISTEN”或“ESTABLISHEN”结尾的行
netstat -tan |grep -E “(LISETN|ESTABLISHED)[[:space:]]*"
netstat -tan | grep -E "LISTEN|ESTABLISHED\>"
10、取出当前系统上所有用户的shell,要求:每种shell中显示一次,且升序排序显示
cut -d: -f7 /etc/passwd|sort -u
挑战题: 写一个模式,能够匹配真正意义上的IP地址: (1.0.0.1–223.255.255.254)
ifconfig | grep -E --color=auto "\<([1-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\>\.){3}"
第一篇博客:将清楚grep和egrep的使用
bash脚本练习
让用户指定一个文件,判断如果文件有空白行,就显示空白行数,否则,就说明文件无空白行
#!/bin/bash
#
read -p "Enter a file path: " filename
if grep "^$" $filename &> /dev/null; then
Count=` grep "^$" $filename | wc -l `
echo "$filename has $Count space lines"
else
echo "no space line"
fi
练习:写一脚本,实现如下功能:
1、让用户通过键盘输入一个用户名
2、如果用户存在,就显示其用户名和UID;
3、否则,就显示用户不存在;
#!/bin/bash
read -p "please input userName :" userName
if grep "^$userName\>" /etc/passwd &>/dev/null ; then
echo "$userName :`id -u $userName` ";
else
echo "no $userName";
fi
练习:写一脚本,实现如下功能:
1、让用户通过键盘输入一个用户名,如果用户不存在就退出;
2、如果用户的UID大于等于500,就说明它是普通用户;
3、否则,就说明这是管理员或系统用户;
#!/bin/bash
read -p "please input userName: " userName
if grep "^$userName\>" /etc/passwd & > /dev/null;then
id=`id -u $userName`
if [ $id -ge 500 ];then
echo "then $userName is putong user"
else
echo "The $userName is root root"
fi
else
echo "$userName is not OK !!";
fi
练习:写一脚本,实现如下功能:
1、让用户通过键盘输入一个用户名,如果用户不存在就退出;
2、如果其UID等于其GID,就说它是个”good guy”
3、否则,就说它是个“bad guy”;
#!/bin/bash
read -p "please input userName: " userName
if grep "^$userName\>" /etc/passwd & > /dev/null;then
id=`id -u $userName`
g=`id -g $userName`
if [ $id -eq $g ];then
echo "$userName is good guy";
else
echo "$userName is bed guy";
fi
else
exit 6
fi
练习:写一个脚本,实现如下功能:
1、添加10个用户stu1-stu10;但要先判断用户是否存在;
2、如果存在,就用红色显示其已经存大在
3、否则,就添加此用户;并绿色显示;
4、最后显示一共添加了几个用户;
#!/bin/bash
for i in {1..10};do
if grep "^stu$i>" /etc/passwd &> /dev/null;then
echo -e "\033[31m stu$i \033[0m is sunflly"
else
useradd stu$i&&echo -e "useradd \033[32m stu$i \033[0m is suefully"
fi
done