回顾:

变量:

本地变量(set)、局部变量(local)、环境变量(export)、位置变量($1,...)、特殊变量($?、)

文本处理命令:

wc, cut, tr, sort, uniq




shell的特性之十:输入输出重定向和管道


I/O: 设备, 寄存器,

I/O port


Linux: 一切皆文件

名称解析:


文件描述符:file descriptor, FD

是内核用来追踪新开打文件属性的内存结构,需要内存空间来存储,因此不能允许用户任意打开文件,分为系统级别和用户级别

linux上一切皆文件,因此一切的操作通路都是通过文件,例如键盘也是对应的一个设备文件,因此会有相应的文件描述符,内核管理

web server: 进程:()


INPUT:标准输入,stdin, 0 ,通常指键盘

OUPUT: 标准输出,stdout, 1,正确文件输出,一般指显示器

  标准错误:stderr, 2,错误文件输出

例如:tr指令就是默认从标准输入读数据,标准输出,可以用I/O重定向来更改路径:

[zhenzhen@zhenzhen ~]$ tr 'a-z' 'A-Z' < /etc/fstab

将输入数据定位/etc/fstab



I/O重定向:指明文件的输入输出是指向哪个文件的,例如如果指向了普通文件,则输出到文件,如果指向了显示器设备文件,则直接显示

指定文件!!!!!

输入重定向:<, <<

<: 输入重定向

[root@zhenzhen ~]# cat < /etc/fstab  和cat+file 一样


<< EOF: 此处创建文件, Here Document

常用于在脚本中创建文件或生成菜单;


a: show user info

d: show disk info

c: show cpu info

b: show group info

脚本文件:

#!/bin/bash


cat > /tmp/out << EOF

b

c

d

EOF

EOF之间会形成一个文件,作为cat的输入,再输出



输出重定向:>, >>

>: 覆盖输出,原有内容会被覆盖

>>: 追加输出

例如:ls /var > /tmp/vat.out

指令:set -C:禁止使用覆盖重定向至已经存在的文件;

指令:set +C: 关闭上述特性;

>|:在-C特性下,强制使用覆盖重定向;


/dev/null: bit bucket,位桶

[zhenzhen@zhenzhen ~]$ ls /etc > /dev/null

[zhenzhen@zhenzhen ~]$ echo $?

0


错误重定向:2>, 2>>

2>: 覆盖

2>>: 追加


同时重定标准输出和错误输出:

COMMAND > /path/to/outfile 2> /path/to/errfile

COMMAND &> /path/to/somefile

COMMAND > /path/to/somefile 2>&1  

例如:

[zhenzhen@zhenzhen ~]$ ls /etc > /tmp/etc.out 2> /tmp/etc.err

这个就是定义两个输出定向,一个正确输出的文件;一个错误输出的文件

[zhenzhen@zhenzhen ~]$ ls /etc &> /tmp/some

&>的意思是正确或者错误都输出到一个文件中

[zhenzhen@zhenzhen ~]$ ls /etc >&1

>&1代表1是显示器文件,因为默认1是显示器文件

[zhenzhen@zhenzhen ~]$ ls /etc > /tmp/etc.out 2>&1

因为前面有 > /tmp/etc.out 因此1指定的是这个 

[zhenzhen@zhenzhen ~]$ lss /etc > /tmp/etc.out 2>&1

  错误的话也是/tmp/etc.out位置


管道:一个指令的输出作为另一个指令的输入

Linux: 

使用目的单一的小程序

组合小程序完成复杂任务


COMMAND1 | COMMAND2 | COMMAND3 | ...

前两个命令是在当前shell中,第三个命令是在子shell中;

不能在前面两个生产的变量然后第三个用


管道和重定向:

重定向是指令输出到文件;

管道是指令输出直接进入到另一个指令


[root@zhenzhen ~]# cat /etc/rc.d/rc.sysinit | tee /tmp/a.out | wc -l

680

这条指令是管道输出到另一个指令之前会把结果重定向存在一个文件中,中间可用tee



bash中的算术运算

默认变量格式是字符串;


declare

-i: 整型变量

-x: 环境变量, 类似于export


let varName=算术表达式

varName=$[算术表达式]   这个也可以执行算数表达式

varName=$((算术表达式)) 这个也可以执行算数表达式

[root@zhenzhen ~]# sumsum=$[$num*$num1]

[root@zhenzhen ~]# echo $sumsum

200

varName=`expr $num1 + $num2` 这里使用反引号


如果计算结果中存在小数,将会被圆整:


操作符:+, -, *, /, %

+=, -=, *=, /=, %=


totalWeight=40


totalWeight=$[$totalWeight+1]

let totalWeight+=1

let totalWeight++


以下是练习题:

练习:计算100以内所有正整数之和;

#!/bin/bash

#

declare -i sum=0

for i in {1..100}; do

 let sum=$sum+$i

done


echo "The sum is: $sum."




知识点:bash的单步执行:

bash -x /path/to/script

-x表示单步执行,会显示执行过程




练习:分别计算100以内所有偶数之和和奇数之和;

#!/bin/bash

declare -i oddSum=0,evenSum=0


for i in `seq 1 2 100`; do

 oddSum=$[$oddSum+$i]

done


for j in `seq 2 2 100`; do

evenSum=$[$evenSum+$j]

done


echo "The Even Sum is: $evenSum, the odd sum is: $oddSum"


练习:计算当前系统所有用户的ID之和;


#!/bin/bash

declare -i uidSum=0

for i in `cut -d: -f3 /etc/passwd`; do

uidSum=$[$uidSum+$i]

done


echo "The UIDSum is: $uidSum."


练习:计算/etc/rc.d/rc.sysinit、/etc/init.d/functions和/etc/issue三个文件的字符数之和;

#!/bin/bash

#

declare -i bytesCount=0

for file in /etc/rc.d/rc.sysinit /etc/init.d/functions /etc/issue; do

let bytesCount=$bytesCount+`wc -c $file | cut -d' ' -f1`

done


echo $bytesCount


练习:新建用户tmpuser1-tmpuser10,并计算他们的id之和;

#!/bin/bash

#

declare -i uidSum=0

for i in {1..10}; do

useradd tmpuser$i 

let uidSum=$uidSum+`id -u tmpuser$i`

done



知识点:位置参数

位置参数:

/tmp/test.sh 3 89 

$0: 脚本自身

$1: 脚本的第一个参数,在脚本中对应3

$2

...

[root@zhenzhen ~]# vi shell3.sh

#!/bin/bash


echo "the add is $[$1+$2]"

[root@zhenzhen ~]# bash shell3.sh 1 2

the add is 3


特殊变量:

$#: 位置参数的个数;

$*,$@: 引用所有的位置参数,即提取所有参数;


知识点:交互式脚本

read

[root@zhenzhen ~]# read num1

123

[root@zhenzhen ~]# echo $num1

123


-p 在read后可以添加"..",显示

[root@zhenzhen ~]# read -p "hello" num    有-p则说明后面的""里为提示信息

hello123


知识点:给变量以默认值

varName=${varName:-value}  提供默认值

如果varName不空,则返回varName的值;否则,则返回value;

如果varName不空,则其值不变;否则,varName会使用value作为其值;

[root@zhenzhen ~]# a=10

[root@zhenzhen ~]# b=${a:-40}  a有值则用a

[root@zhenzhen ~]# echo $b

10

[root@zhenzhen ~]# unset a

[root@zhenzhen ~]# b=${a:-40}  a没有值则使用40

[root@zhenzhen ~]# echo $b

40


脚本:

[root@zhenzhen ~]# vi shell4.sh

#!/bin/bash

read -t 5 -p "input a number: " num    这里的-t是等多少秒的意思

num=${num:-100}  num有值则用num的,没有值则使用默认值100

echo $num


练习:通过键盘给定一个文件路径,来判断文件内容的类型;

read -p "input the filepath" filename

file $filename

练习:通过键盘给定一个目录路径,默认为/,来判断目录下文件内容的类型;