Shell学习

来源:互联网 发布:淘宝店铺复核认证方法 编辑:程序博客网 时间:2024/06/05 08:06
#shell一些概念
(1)shell脚本就是将其他工具串联在一起的一门语言,既要了解shell,也要了解每个工具是用来做什么的。
(2)unix最初是1970年由贝尔实验室开发出来的
(3)编译性语言主要是通过编译器编译成目标代码,然后由机器执行,执行效率比较高;解释型语言主要通过解释器解释执行,效率比较低,但是在编译性语言的上层。


#shell脚本学习
(1)如何编辑文件,并且生成.sh脚本
通过 cat 或者 vi 来编辑文档,然后在文档的开头写上 #!/bin/sh 用于指明由什么脚本解释器执行,对于该文件,通过
chmod +x filename  来改变文档的可执行属性,这样就可以执行了。


(2)各种引号的作用
无引号:就是普通的字符串 但是字符串与字符串之间不能有空格
单引号:字符串,但是不支持变量的替换  所谓的变量的替换就是指在字符串中应用到了变量
双引号:字符串,允许变量的替换
反单引号:把反单引号之间的作为命令执行,然后结果作为字符串


(3) if 语句
myvar="hello" #赋值语句等号左右不能有空格
if [ $myvar = "hello" ] #用中括号;前后都有空格;判断等号左右都有空格
then echo "hello"
elif [ $myvar = "no"] #elseif -> elif
then echo "no"
else echo "else" #else
fi  #结束if


(4) 读取文件语句
while read line #命令使用read
do              #do  
echo line
done < user.txt  #done


(5) while 语句
i=0
sum=0
while [ $i -le 50 ]  #莫要忘记空格
do
sum=$(($sum + $i)) #莫要忘记算数计算的方式  最外面要加上$ 而且是双层单括号
i=$(($i+1))
done


(6) grep
有三种程序可以用来查找文本文件:grep egrep fgrep
grep "name" user.txt
grep name user.txt 

以上两者都是一样的
grep -选项  参数(name)  参数(user.txt)


(7) sed
http://coolshell.cn/articles/9104.html
find /home/tolstoy -type d -print |  #找到/home/tolstoy目录下面的所有的文档并且打印出名字
sed 's;/home/tolstoy/;/home/lt/;' |  #这里用;作为限界符,意思是把/home/tolstoy重改名为/home/lt/
sed 's/^/mkdir /' |     #在每一个文档名前面加上mkdir 其实就是创建文档的意思
sh -x  #跟踪执行脚本


(8) awk
http://coolshell.cn/articles/8883.html
http://coolshell.cn/articles/9070.html
某些地方和sed 差不多,而且还能做到对每一行数据字段的处理。
awk 'pattern action' filename  一般都指明模式以及动作
ll | awk '{print $1}'  #这个就没有模式的概念  但是指定了动作  打印第一个字段
ll | awk 'NF > 0 {print $1}' #这个就有了模式和动作
awk -F: -v 'OFS=**' '{ print $1, $5 }' /etc/passwd  #以:作为分隔符,以**作为字段之间连接的字符,打印出第一个和第五个字段
awk -F: '{print $1 " my description is " $3}' #也可以对于打印出的数据做字符串连接


awk '{print $1, $4}' netstat.txt  #输出文件netstat.txt的第一列和第四列
awk '{printf "%-8s %-8s %-8s %-18s %-22s %-15s\n",$1,$2,$3,$4,$5,$6}' netstat.txt  #利用printf 按格式打印输出
awk '$3==0 && $6=="LISTEN" ' netstat.txt  #通过判断条件过滤选项  获取所需的内容
$ awk ' $3>0 {print $0}' netstat.txt  #增加了判断条件  只打印第一列
$ awk '$3==0 && $6=="ESTABLISHED" || NR==1 {printf "%02s %s %-20s %-20s %s\n",NR, FNR, $4,$5,$6}' netstat.txt  #中间加上了或条件,而且打印出了行号  NR 行数  NF行里面的列出  FNR:读取本文档的时候的行数
awk  'BEGIN{FS=":"} {print $1,$3,$6}' /etc/passwd #设置指定分隔符号
awk -F: '{print $1,$3,$6}' /etc/passwd  #和上一句的作用是一样子的
awk  -F: '{print $1,$3,$6}' OFS="\t" /etc/passwd  #:作为分隔符,然后打印出1 3 6列,中间通过制表符连接
-F '[;:]'   #也可以设置多种分隔符
awk '$6 ~ /FIN|TIME/ || NR==1 {print NR,$4,$5,$6}' OFS="\t" netstat.txt   #~代表模式的开始   //连个斜杠中间的内容就代表正则表达式   
awk 'NR!=1{print > $6}' netstat.txt   #拆分文件  根据第六列内容  自动拆分文件为几个小文件
awk -F: '{print $1 $4 > $2}' netstat.txt  #为每一个拆分出来的文件中存入字段


awk 'NR!=1{if($6 ~ /TIME|ESTABLISHED/) print > "1.txt";
else if($6 ~ /LISTEN/) print > "2.txt";
else print > "3.txt" }' netstat.txt   #awk的行为里面可以加入if else这种语句   awk更像一个命令解释器


$ ls -l  *.cpp *.c *.h | awk '{sum+=$5} END {print sum}'  #awk用于做统计也非常的牛逼


BEGIN{ 这里面放的是执行前的语句 }
END {这里面放的是处理完所有的行后要执行的语句 }  #在awk里面经常遇到的
可以写好一个脚本文件,里面就只有BEGIN{} {} END{} 然后通过 awk -f fileName  targetFile 就可以实现对该内容的整理

(9) 输入输出流 < > >>
unix默认的输入,输出,错误输出都是指向终端。可以通过重定向的方式修改输入输出地址。
tr -d '\n' < source.txt  > target.txt
通过< >符号就可以制定输入流和输出流,上面一句的意思就是把输入流source.txt里面内容的换行符删除,不修改原有的source.txt,然后把结果存储到target.txt里面。
>如果文件不存在,创建一个新的文件,如果文件存在,那么就直接覆盖原有的内容
>> 如果文件不存在,创建一个新的文件,如果文件存在,那么就把内容连接到现有文件的后面。


(10) /dev/null /dev/tty
有些文件输出比较大,可能不希望打印,也不希望存入文件,那么就可以把数据输出到/dev/null中 
/dev/tty  一般都是作为输入流  当使用这个的时候如  read pass < /dev/tty  那么就会打开一个终端用于输入数据了
stty -echo 关闭输入字符时候的提醒 一般输入密码的时候常常用到
stty echo 重新开启输入时候显示的功能


(11) 命令的查找路径问题
环境变量$PATH 里面存储着所有可执行文件的地址,在执行命令的时候,系统会查找对应路径下是否有该指令。往往命令都放到bin目录下面,然后可以通过在$PATH后面增加上路径来把
自己的命令加进去。
另外,还可以在PATH中增加一个:来表示当前目录的搜索顺序。


(12) 正则表达式
http://www.cnblogs.com/caibird2005/archive/2009/04/14/1436008.html
正则表达式有两个基本部分组成:一般字符和特殊字符
[]表达式可以用来表示字符的范围 [:alpha:] 所有的字符 [0-9] 数字0-9 [0-9a-fA-F]也是三段范围
排序:[ab[.ch.]de] a b  d  e  ch都可以匹配
等价字符集:[a[=e=]fe] 凡是和e是等价字符都会计算在内
后项引用:\(ab\)\(cd\)[def]*\2\1  包含在\(以及\)之间的部分可以在后面通过编号的方式引用之。
文本匹配锚点:[[:upper:]]\{3\}   居中的4Ÿ、5、6abcABCdefDEF便满足搜索条件  前置单个字符出现的重复次数  通过在需要的字符后面加上\{数字\}来实现就可以了
交替: egrep "ab|name" filename   或者 grep -E "ab|name" filename 查找filename中包含ab和name的内容


(13) 对于字段的处理
ls -s | cut -c 1-10  列举出所有的文档及其信息,然后以字符的形式获取里面1-10的字符
ls -s | cut -d " " -f 1,2 以空格为分割符  然后取出从第1到第2的元素


(14) 特殊变量
$# 参数个数
$? 最近一次命令执行退出码
$$ 当前进程号
$* 所有参数组成的一个字符串
$@ 所有参数组成的多个字符串 (每参一个)
$! 后台运行的最后一个进程号
$0 当前进程名


(15) 判断语句
字符串比较:
!expression # 非
expr1 -a expr2 # 与
expr1 -o expr2 # 或
整数大小比较:
n1 -gt n2 # 大于
n1 -lt n2 # 小于
n1 -ge n2 # 大于等于
n1 -le n2 # 小于等于
n1 -eq n2 # 相等
n1 -ne n2 # 不等
文件判断:
-r file # 文件存在且可读
-w file # 文件存在且可写
-x file # 文件存在且可执行
-f file # 文件存在且为普通文件
-d dir # 文件存在且为目录
-c file # 文件存在且为字符设备文件
-b file # 文件存在且为块设备文件


(16) case 语句
i=$1
case $i in  #case .. in
1)     #当为1的时候  就和一项一项的小括号一样
  echo "hello"
  echo "first";;  #别忘记了是两个分号
2)
  echo "second";;
*)
  echo "default"
esac


(17) for 语句
filelist=`ls`    #通过调用命令获取到的是一组结果
for file in $filelist  #for i in list
do                     #do done
   if [ -f file]       #判断是否为文件
   then
echo "file"
   else
     echo "not file"
   fi                  #if结束符  else没有then
done


(18) until 语句
i=1
until [ $i -gt 50]   #和while语句差不多  只是条件变成了终止条件
do
 i=$(($i + 1))
done
echo "${i}"


(19) 循环控制
break 跳出当前
break N 跳出最内基层循环
continue
continue N


(20)函数定义以及函数引用
function function1(){      #定义函数  可以加上function,也可以不加
echo "function1 is running"
}


function2(){
echo $1,$2   #查看传入的两个参数
return $(($1+$2))  #返回结果
}


function1  #调用函数  直接写名称就可以
total=$(function2 1 2)  #获取函数的返回值
echo "${total},$?"  #打印返回值 $?


#以下是在另外一个文件中引用只包含函数定义的脚本时的引入与调用代码
source "file"
function2 


(21) 判断某一个变量是否存在的时候
if ["$PATH" = ""] 这样做
[[ $1 = "sessionmember" ]] 或者这样做


(22) 连接mysql
http://www.cnblogs.com/xiaochaohuashengmi/archive/2011/10/18/2216279.html
mysql -u 用户名 -p 密码  -h host -P 端口  数据库名


(*) 学习的命令例子
who 查看在线用户
who | wc -l  通过|建立管道,把前面的输出当做是后面的输入,然后cw -l用于记录行数
cat filename 显示文件内容
cat > filename 写入文件内容  ctrl+D 是文档结尾的意思
command option argument  命令,选项,参数
多个命令之间可以用;隔开,表示一条一条的执行,如果是用&隔开,则表示可以不等待前面的执行结束就可以执行后面的命令。
shell里面变量可以为空,null
shell里面的字符串变量的数值长度是没有限制的
printf "hello %s %s" zhang xinglong  shell里面的printf和c语言中的差不多
sh -x shellName 可以实现简单调试脚本的作用
echo ${myvar:=word} 推荐使用{},如果myvar不存在,则打印world
echo ${myvar:?error}}  如果myvar不存在,报错
; 按顺序执行  && / || 短路表达式执行后续命令   & 之前命令后台执行


(*)分析脚本时学习
(1)date +%Y-%m-%d -d "1 days ago"  获取昨天的时间 2014-07-22


(2)cd `dirname $0`
filepath=`pwd`  进去当前目录 并且打印路径


(3)source ../common.conf  可以加载某些文件,比如在该例子中就是一些环境变量的设置
source命令用法:
source FileName
作用:在当前bash环境下读取并执行FileName中的命令。


(4)if [ ! -d "$1" ];   #判断传入的参数是否存在且为目录 
then
mkdir $1   #如果不是  那么创建目录
fi


(5)exit 0  #退出

(6)sh a.sh a a,b,c d  算是三个参数a  a,b,c  d


(7)下面两种for循环写法都可以
LIST="rootfs usr data data2"          
for d in $LIST; do
用for in语句自动对字符串按空格遍历的特性,对多个目录遍历
for i in {1..10}


(8)$expr 10 + 10   #简单的四则运算  别忘记空格
20 
$expr 1500 + 900 
2500 
$expr 30 / 3 
10 
$expr 30 / 3 / 2 
5


(9) seq 1000   默认生成从1 跨度为1 到1000的所有数字
    seq 3 1000 从3 跨度1 到1000
    seq 2 10   从2  跨度1 到10
    seq 1 2 10  从1  跨度2  到10


(10) sort -k 3 -n -r | head -15  进行排序,并且取前15名
(11) sort  -u 唯一  -r  降序 -n 以数值来排序  -k 制定排序的列  -t  指定分隔符
(12) read a b c < filename   如果第一行是通过空格隔开的数据   那么就分别读取到了a b c中


(*)python 学习
(1)在shell脚本中调用python脚本,传入的参数获取方式:
import sys
a = sys.argv[1]  #开始下标为1


(2)headUrlDict = dict() #声明一个词典
d = dict()
t = tuple()
l = list()
s = set()


(3)datas = line.strip().split("\t") 字符串根据制表符进行划分,取出数据datas[0]
(4)d = groupDict[key]  也可以根据key直接输出
(5)list = line.strip().split("\t")
userId,msgId = tuple(list)  #对于元组  可以如此赋值
 
(6)sys.argv[0]  可以获取代码本身所在的路径
(7)lambda只是一个表达式,函数体比def简单很多。
f = lambda x,y,z: x+y+z
f(1,2,3)  返回6



(*)hadoop脚本
hadoop fs -rm filenmae #删除文件  -rmr 就是把子目录里面的所有也删除了
hadoop fs -ls documentname #查看文件夹下内容  -lsr 就是也呈现出子目录里面的内容
hadoop fs -mkdir filename  #创建文件夹
hadoop fs -get filename  #下载文件
hadoop fs -put filename  #上传文件
hadoop fs -cat filename  #查看文件
hadoop jar filename.jar  #提交某个job
hadoop job -kill jobname  #杀死某个job



学习网址:
http://wiki.d.xiaonei.com/pages/viewpage.action?pageId=22872316



0 0