shell 编程

单引号、双引号、反引号、无引号

单引号:单引号被识别为普通字符串,就是不识别引号里面的特殊字符,属于强引用。

双引号:双引号里面的特殊字符是可以被识别的,是弱引用。

反引号:在linux中,反引号中的内容一般是一行或多行命令,当这些命令被反引号引着,命令执行结果就会以字符串的形式被保留下来。

无引号:如何是连续的符号可以不加引号,但是如果有空格就有歧义,最好使用双引号。

在unix系统中,程序会分析#!字符后面的内容,作为解释器的指令,比如: 以#!/bin/sh 开头的文件,程序在执行的时候会调用/bin/sh,也就是bash解释器 以#!/usr/bin/python 开头的文件,就代表指定python解释器去执行。 如果没有指定shebang,脚本执行的时候就默认用shell去解释脚本。

yum install psmisc -y pstree

文本处理

cut
sort
wc
sed  >  vi
awk

cut:显示切割的行数据 f:选择显示的列 s:不显示没有分隔符的行 d:自定义分隔符 sort:排序文件的行 n:按数值排序 r:倒序 t:自定义分隔符 k:选择排序列 u:合并相同行 f:忽略大小写

type:命令类型
外部命令  &  内部命令
help:内部命令帮助
help:内部命令清单,附带语法格式,描述
help 具体内部命令
man:帮助手册manual
yum install man man-pages -y
whereis : 定位命令位置
file:文件类型
echo:打印到标准输出
$PATH: 环境变量:路径
$LANG
/etc/profile  》  bash启动(交互方式)


变量:


a=3
echo $a
b=(1,2,3)
echo $b
b=(1 2 3)
echo $b
echo hello$agod
echo hello${a}god
echo ${b[2]}


  • Filesystem Hierarchy Standard(文件系统层次化标准)
    • /boot: 系统启动相关的文件,如内核、initrd,以及grub(bootloader)
    • /dev: 设备文件
    • /etc:配置文件
    • /home:用户的家目录,每一个用户的家目录通常默认为/home/USERNAME
    • /root:管理员的家目录;
    • /lib:库文件
    • /media:挂载点目录,移动设备
    • /mnt:挂载点目录,额外的临时文件系统
    • /opt:可选目录,第三方程序的安装目录
    • /proc:伪文件系统,内核映射文件
    • /sys:伪文件系统,跟硬件设备相关的属性映射文件
    • /tmp:临时文件, /var/tmp
    • /var:可变化的文件
    • /bin: 可执行文件, 用户命令
    • /sbin:管理命令 df:显示磁盘使用情况 du:显示文件系统使用情况 ls:显示目录 cd:切换工作目录 pwd:显示当前工作目录 mkdir:创建目录 rm:删除 cp:拷贝 mv:移动 ln:链接 stat:元数据 touch

groupadd groupdel useradd userdel usermod id passwd sudo
su r w x 1 0 1

useradd sxt01 passwd sxt01 useradd sxt02 passwd sxt02

mkdir /var/swapdata 1,权限修正: chmod 770 swapdata | chmod o-rwx g+rwx swapdata 2,修正属组 groupadd sxtswap usermod -a -G sxtswap sxt01 usermod -a -G sxtswap sxt02 chown root:sxtswap swapdata chown :sxtswap ooxx.file chmod 770 ooxx.file id username

打开文件 vim /path/to/somefile vim +# :打开文件,并定位于第#行 vim +:打开文件,定位至最后一行 vim +/PATTERN : 打开文件,定位至第一次被PATTERN匹配到的行的行首 关闭文件 末行模式: :q 退出 没有动过文件 :wq 保存并退出 动过了,不后悔 :q! 不保存并退出 动过了,后悔了 :w 保存 :w! 强行保存 :wq --> :x

ZZ: 保存并退出 不需要冒号,编辑模式

sed:行编辑器

sed [options] 'AddressCommand' file ... -n: 静默模式,不再默认显示模式空间中的内容 -i: 直接修改原文件 -e SCRIPT -e SCRIPT:可以同时执行多个脚本 -f /PATH/TO/SED_SCRIPT -r: 表示使用扩展正则表达式

sed:行编辑器Command d: 删除符合条件的行; p: 显示符合条件的行; a \string: 在指定的行后面追加新行,内容为string \n:可以用于换行 i \string: 在指定的行前面添加新行,内容为string r FILE: 将指定的文件的内容添加至符合条件的行处 w FILE: 将地址指定的范围内的行另存至指定的文件中; s/pattern/string/修饰符: 查找并替换,默认只替换每行中第一次被模式匹配到的字符串 g: 行内全局替换 i: 忽略字符大小写

s///: s###, s@@@	
	\(\), \1, \2

sed:行编辑器Address 可以没有 给定范围 查找指定行/str/

awk

$0
当前数据
$1

$2

awk是一个强大的文本分析工具。 相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大。 简单来说awk就是把文件逐行的读入,(空格,制表符)为默认分隔符将每行切片,切开的部分再进行各种分析处理。

awk -F '{pattern + action}' {filenames}

  • awk -F '自定义分隔符' ‘BEGIN{} 匿名{ fun } END{}’ 支持自定义分隔符 支持正则表达式匹配 支持自定义变量,数组 a[1] a[tom] map(key) 支持内置变量
变量描述
ARGC命令行参数个数
ARGV命令行参数排列
ENVIRON支持队列中系统环境变量的使用
FILENAMEawk浏览的文件名
FNR浏览文件的记录数
FS设置输入域分隔符,等价于命令行 -F选项
NF浏览记录的域的个数
NR已读的记录数
OFS输出域分隔符
ORS输出记录分隔符
RS控制记录分隔符

支持函数

  • print、split、substr、sub、gsub

支持流程控制语句,类C语言

if、while、do/while、for、break、continue

awk -F':' 'BEGIN{print "name,shell"} {print $1 "," $7} END{print "blue,/bin/nosh"}' passwd

#!/bin/bash

dict=$1

echo find path is  ${dict}
oldIFS=$IFS

IFS=$'\n'

res=$( du -a $1 | sort -nr )

for i in $res; do

#filename=`awk '{print $1}'  $i`
echo $i;
#	echo $filename;
#	if [ ]

done



 ./findMax.sh  /home | awk '{print $2}'

统计报表:合计每人1月工资,0:manager,1:worker
Tom	 0   2012-12-11      car     3000
John	 1   2013-01-13      bike    1000
vivi	 1   2013-01-18      car     2800
Tom	 0   2013-01-20      car     2500
John	 1   2013-01-28      bike    3500

awk '{split($3,date,"-");if(date[2]=="01"){name[$1]+=$5;if($2=="0"){role[$1]="M"}else{role[$1]="W"}}} END{for(i in name){print i "\t" name[i]"\t" role[i]}}' awk.txt

shell

shell bash 解释器,启动器 解释器: 用户交互输入 文本文件输入 脚本本质:

#! /bin/bash
#! /usr/bin/python

读取方式: 当前shell:source/. 新建子shell:/bin/bash file / ./file.sh 《chmod +x file.sh》 函数 命令概念总结

脚本是一个文本文件!

#!/bin/bash
./testFile
    #!  /bin/bash (/usr/bin/python)
    先启动/bin/bash -f testFile
    ~~  新开启一个shell :然后执行source testFile
  • 文本流&重定向
  • 变量
  • 引用&命令替换
  • 退出状态&逻辑判断
  • 表达式
  • 流程控制

文本流&重定向

重定向:不是命令 程序自身都有I/O 0:标准输入 1:标准输出 2:错误输出 控制程序I/O位置 一切皆文件 /proc/$$/fd 程序是否处理I/O? 绑定顺序:从左到右

输出重定向: 修改程序的1或2

> 覆盖源
>> 追加
&> , >&   

输入重定向:

<  一个脚本 .sh .py

<< 后缀匹配结束
read bb 0<<ooxx
adfjadlfj
asdjf;lasjdf
asdfjdlasfkj
jdsf;
ooxx

<<<   
read aa 0<<<"public void"
  • exec
    • 替换当前shell

变量

变量

  • 本地 本地: 当前shell拥有 生命周期随shell name=god 局部: 只能local用于函数 val=100
  • 位置:
    • ${}
    • $1,$2, ${11}

环境变量导出

环境变量:env,printenv,export export定义变量 导出到子shell

fork() Copy On Write O(1)

  • parent 3g ==> child 3g 环境变量

    • 进程 子进程 引用传递 环境变量
    • 指针地址的引用
    • Copy On Write 写时复制
    • 物理计算机= 内存条 = 线性地址空间
      • 物理地址 虚拟地址 映射关系
      • CPU MMU 内存管理单元
    • 写时复制,并无复制那么高的成本,是更改的指针引用
      1. 父进程启动,增加变量a = 2 ,在内存中开辟一个空间 2 ,父进程指针指向此地址的,
      2. 在使用 /bin/bash 开辟子进程后,子进程的a 同样指向内存中地址,当子进程中修改a的值后,在内存中,开辟一个新值的空间,将子进程指针指向此地址
    • 父进程,子进程。。 均为系统进程 维护虚拟地址
    • java
  • 适用于函数 unset:取消变量 set:查看shell的变量

命令替换:

  • 接收变量等
    • 反引号:ls -l /
    • " lineq=ls -l|wc -l "
    • $(ls -l /)
    • 可以嵌套

算术表达式

let  算术运算表达式
let  C=$A+$B
$[算术表达式]
C =$[$A+$B]
$((算术表达式))
C=$(($A+$B))
expr  算术表达式  
注意:表达式中各操作数及运算符之间要有空格。而且要使用命令引用
C=`expr $A + $B`

help let

条件表达式

help test

test 15 -gt 8 && echo 'is true'

[test 15 -gt 8] && echo 'is true'

[  expression  ]
test expression
[[ expression ]]

help test

脚本 函数

特殊:

位置shell

  • $#:位置参数个数
  • $*:参数列表,双引号引用为一个字符串
  • $@:参数列表,双引号引用为单独的字符串
  • $$:当前shell的PID:接收者 $BASHPID:真实 管道 echo $?:上一个命令退出状态 0:成功 other:失败

[root@dock01 app]# cat param.sh 
#!/bin/bash

echo $$ 

echo $#

echo $*

echo $@ 

echo $1

echo 'end'

[root@dock01 app]# ./param.sh  1 2 3 4 5 6 7 8 9 
9307
9
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9
1
end
[root@dock01 app]# 

  • add User Shell
#!/bin/bash
userName=$1

echo 'add $userName'
# 添加用户
# useradd 
# 用户密码同用户名
# 静默运行脚本
# 避免捕获用户接口
# 程序自定义输出

#!/bin/bash

[ ! $# -eq 1  ] &&  echo "args error"  &&  exit 2

 id $1 >& /dev/null  &&  echo "user:$1  exist~!" &&  exit 3

 !  useradd $1  >&  /dev/null   &&  echo "add user error!" &&  exit  7
echo $1  |  passwd --stdin $1 >& /dev/null


echo "user:$1 add ok ~!"


流程控制

shell if

if [  express  ] ; then xxx ; else xxx ; fi
[root@dock01 app]# if [ 3 -eq 6] ; then echo okk; else echo no ok; fi
bash: [: missing `]'
no ok
[root@dock01 app]# if [ 3 -eq 6 ] ; then echo okk; else echo no ok; fi

while for

  • for (( exp1; exp2; exp3 )); do COMMANDS; done
[root@dock01 app]# for ((i=1;i <11 ; i++  )) ; do echo ${i} ;     done

  • for NAME [in WORDS ... ] ; do COMMANDS; done case

循环遍历文件每一行:流程控制语句 定义一个计数器num 打印num正好是文件行数

管道 重定向 命令替换

#!/bin/bash

num=0
oldIFS=$IFS
IFS=$'\n'
for i in `cat file.txt`;do
	echo $i
	((num++))
done
echo "num:$num"
IFS=$oldIFS
echo "--------------"

num=0
lines=`cat file.txt | wc -l `
for ((i=1;i<=lines;i++));do
	line=`head -$i file.txt | tail -1`
	echo $line
	((num++))
done
echo "num:$num"
echo "--------------"
num=0
while read line    ;do
	echo $line
	((num++))
done < file.txt
echo "num:$num"
echo "--------------"
export num=0
cat file.txt | while read line  ;do 
	echo $line
	((num++))
done
echo "num:$num"




#!/bin/bash
oldIFS=$IFS
IFS=$'\n'
flg=0
for i in ` du -a $1 | sort -nr`;do
	fileName=`echo $i | awk '{print $2}'`
	if [ -f $fileName ];then
		echo $fileName
		flg=1
		break
	fi

done

IFS=$oldIFS

if [ $flg -eq 0 ];then
	echo "not find"  &&  exit 2
else
	exit 0
fi








1,花括号 mkdir -p sdfsdf/{a,b,c}sdfsdf 2,波浪线 cd ~god 3,变量&参数 $ $$ ${}(.....) 4,命令替换 ls -l echo $path 5,算术扩展 num=((3+4)) 6,word拆分,IFS 7,路径 *(零到多个任意字符)? 8,引用删除 echo "hello" *,重定向 >