分类: 2013-06-30 20:26 7300人阅读 (0) 收藏
按行读取文件
[cpp]
#!/bin/bash
echo "##### 方法 1 #####"
while read line1
do
echo $line1
done < $1
echo "##### 方法 2 #####"
cat $1 | while read line2
do
echo $line2
done
echo "##### 方法 3 #####"
for line3 in $(<$1)
do
echo $line3
done
运行结果
snail@ubuntu:5.read-line$ cat file.bin hello worldthis is 1this is 2this is 3snail@ubuntu:5.read-line$ ./read-line.sh file.bin ##### 方法 1 #####hello worldthis is 1this is 2this is 3##### 方法 2 #####hello worldthis is 1this is 2this is 3##### 方法 3 #####helloworldthisis1thisis2thisis3
使用for读取时,自动按空格作为间隔符。
如果输入文本每行中没有空格,则line在输入文本中按换行符分隔符循环取值.如果输入文本中包括空格或制表符,则不是换行读取,line在输入文本中按空格分隔符或制表符或换行符特环取值.可以通过把IFS设置为换行符来达到逐行读取的功能.
[cpp]
IFS=$'\n'
echo "##### 方法 3 #####"
for line3 in $(<$1)
do
echo $line3
done
hello world!
#! /bin/bashecho “hello world!”$ chmod +x a.sh$ ./a.shhello world!变量变量不分类型 (没有int,char,string)不需要声明,直接使用赋值:name=value (左右两边不能有空格)使用:$name ${name}foo=hecho ${foo}ello变量的作用域默认全局作用域(仅当前shell可见)local 限定函数局部变量function a() { local msg; }使用export导出变量,让子shell可以继承export var=1source 或 .(dot) 在当前shell下执行脚本source ./config.sh变量分类自定义变量环境变量 (set命名可查看)$PATH,$IFS,$PS1,$PWD,$LINENO位置参数(Positional Parameters)$1 $2 $3 … ${10}特殊参数(Special Parameters)$#:位置参数的数量 $*:所有位置参数的内容 ($1 $2 …)$@: 所有位置参数的内容(“$1” “$2” … )$?:命令执行后返回的状态$$:当前进程的进程号 $!:后台运行的最后一个进程号$0:当前执行的进程名玩转变量使用eval实现变量的间接引用x='abc def'y='$x'echo $y$xeval echo $yabc de玩转变量(续)${!p} #双重引用a=1b='a'echo ${!b}1${!p*} #返回所有以p开头的变量 echo ${!P*}PATH PIPESTATUS PPID PS1 PS2 PS4 PWD${p:-word} #如果变量p不存在,返回"word”${p:=word} #如果变量p不存在,返回"word",并将p的值设为"word"${p:?word} #如果变量p不存在,将"word"打入STDERR ${p:+word} #如果变量p存在,返回"word" 玩转变量(续)if [${ret:=1} -ne 0 ]thenecho “NO”exitfi引号迷雾双引号使用双引号可解释$符号,反引号和反斜线等特殊字符echo “$msg” => 显示msg变量值单引号与双引号类似,不同的是shell会忽略任何特殊符号echo ‘$msg’ => 显示$msg 反斜杆\c == ‘c’反引号(命令替换) 用于执行系统命令并输出到变量echo The date and time is `date` 几种括号(list) list将在一个子shell中执行, 不会对当前shell产生影响,返回list的exit值{ list; } 可以作组合命令用,list将在当前shell中被执行,list结尾处必须要有新行或‘;’号,返回list的exit值,list前后必须有空格 ((expression)) 算术计算 [ ] [[ ]] 分支测试数组name=(value1 ... valuen) 此时下标从0开始name[index]=valueunset name 或 name=数组下标的范围没有任何限制,同时也不必使用连续的分量$ A=(a b c def)$ A[3]=bb$ echo ${A[0]} #取第一个元素a$ echo ${A[@]} # 取全部元素a b c def$ echo ${#A[@]} # 取得数组元素的个数4 数组(续)遍历数组:total=${#A[*]}for ((i = 0; i < total; i++))doecho ${A[$i]}done分支语句if list; then command; [ elif list; then command; ] ... [ else command; ]ficase $word in[a-z]) list ;;*) default;;esac[ $# -eq 1 ] && slen=1 || slen=0条件测试对文件、字符串和数字使用test命令。test一般有两种格式:test condition 或 [ condition ](注意空格)if [ $str = “a.txt” ];then echo “OK"fi直接测试命令:if grep abc a.txt &>/dev/null;thenecho “Bingo!”fi条件测试(续)推荐使用[[ ]]进行条件测试if [[ “x$str”== “xa.txt” && -f b.txt ]]thencmd;fi-f -d -z ……man bashCONDITIONAL EXPRESSIONS条件测试 – 数值比较if [ $a –lt 0 ]thenecho OKfi推荐使用(( ))if (( a > 0 ))thenecho OKfi循环语句for name [ in word ] ; do list ; donefor i in `ls *.result`;do cat $i; donefor (( expr1 ; expr2 ; expr3 )) ; do list ;donefor ((i=0;i<100;i++));do echo $i;donewhile list; do list; donewhile read linedoecho $linedone < a.txtuntil list; do list; done注释# 行注释 (#前要有空格)echo $msg #print message块注释:<<COMMENTecho $msgCOMMENTcomment(){ echo $msg}正则表达式基础元字符. 匹配任何单个字符。 $ 匹配行结束符。^ 匹配一行的开始。* 匹配0或多个正好在它之前的那个字符。+ 匹配1或多个正好在它之前的那个字符。? 匹配0或1个正好在它之前的那个字符。\{i\} \{i,j\} 匹配指定数目的字符。\ 这是引用符,转义;[ ] [c1-c2] 匹配括号中的任何一个字符。 [^c1-c2] \< \> 匹配词(word)的开始(\<)和结束(\>)。 将 和 之间的表达式定义为“组”(group),并且将匹配这个表达式的字符保存到一个临时区域(一个正则表达式中最多可以保存9个),它们可以用 \1 到\9 的符号来引用。| 将 两个匹配条件进行逻辑“或”(Or)运算。例如正则表达式(him|her) 正则表达式举例HTML标签<[^>]*> 匹配由26个英文字母组成的字符串 ^[A-Za-z]+$ Email地址\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)* URL[a-zA-z]+://[^\s]*管道和重定向管道可以把一条命令的输出作为另一条命令的输入Command1 | Command2返回值是最后一个命令的返回值重定向wc –l /etc/passwd > a.txtwc –l /etc/passwd >> a.txtwc –l < /etc/passwd./command > a.txt 2>&1 (./command &> a.txt)exec 5<> a.txtecho “hello” >&5<&- >&-作业控制<CTRL-Z> 将当前任务挂起,返回job_idfg job_id 把后台作业放到前台执行bg job_id 把作业放到后台执行vi b.sh<CTRL-Z>[1]+ Stopped vim b.shbg 1[1]+ vim b.sh &fg 1vim b.sh自定义函数function foo() # foo为函数名{ local a=$1; # 局部变量echo $a;return 0; # 返回值}foo “cool!” # 函数调用echo $? # 打印返回值自定义函数 – 16进制转点分十进制a(){ local str=$1 echo -n $((16#${str:0:2})) str=${str:2} if [ "x$str" = "x" ] then echo; return else echo -n "."; a $str fi}#Usagea "DDB14CCF"整数计算id++ id-- ++id –id - + ! ~ ** * / % 计算<< >> & ^ | 位操作<= >= < > == != 比较&& || 逻辑操作expr?expr:expr 三元操作符= *= /= %= += -= <<= >>= &= ^= |= 赋值操作符y=2000 闰年计算echo $((y%4==0 && y%100!=0 || y%400==0)) (( y++ )) 自增1tmp=$((16#a)) 进制转换浮点运算echo “scale=5; 3/7"|bc –l.42857echo "100.43KB 20.12KB" | awk '{print $1-$2}'80.31echo "ibase=16;F"|bc -l 15简单字符串处理x=abcd${#x} # 获取字串长度4expr index $x “b“ # 获取子串所在偏移2expr index $x "a“ # 获取子串所在偏移1 echo ${x:1} # 获取子串bcdecho ${x:2}cdecho ${x:0:2} ab简单的字符串处理(续)x=aabbaarealwwvvwwecho “${x%w*w}“ # 截去尾部最短匹配aabbaarealwwvvecho “${x%%w*w}“ # 截去尾部最长匹配aabbaarealecho “${x##a*a}“ # 截去头部最长匹配lwwvvwwecho “${x#a*a}“ # 截去头部最短匹配bbaarealwwvvww x=abcdabcdecho ${x/a/b} # 只替换一个bbcdabcdecho ${x//a/b} # 替换所有bbcdbbcd简单字符串处理 – 实际应用截去域名尾部name=jx-sys-superdb.jx.baidu.comecho ${name%%.*} jx-sys-superdb截取日期str=20081011year=${str:0:4} 替换echo ${name//jx/tc}tc-sys-superdb.tc.baidu.com随机字符串生成typeset -r DEFAULT_STR_LEN=5typeset -ra dict=(a b c d e f g h i j k l m n o p q r s t u v w x y z)function get_random_letter(){ echo -n ${dict[$((RANDOM%${#dict[*]}))]}return 0}function get_random_string(){ local slen str[ $# -eq 1 ] && slen=$1 || slen=$DEFAULT_STR_LENfor ((i = 0; i < slen; i++))dostr=${str}`get_random_letter`doneecho $strreturn 0}get_random_string $1调试-x-n 是只语法检查而不执行任何命令-e 是脚本发生第一个错误时就中止脚本运行,即当一个命令返回非零值时退出脚本 (除了until 或 while loops, if-tests, list constructs)--posix 是更改Bash或脚本的行为,使之符合POSIX标准Shell 伪信号:EXIT,ERR,DEBUG调试(续)+ typeset -r DEFAULT_STR_LEN=5+ typeset -ra 'dict=(a b c d e f g h i j k l m n o p q r s t u v w x y z)'+ get_random_string 2+ local slen str+ '[' 1 -eq 1 ']'+ slen=2+ (( i = 0 ))+ (( i < slen ))++ get_random_letter++ echo -n t++ return 0+ str=t+ (( i++ ))+ (( i < slen ))++ get_random_letter++ echo -n k++ return 0+ str=tk+ (( i++ ))+ (( i < slen ))+ echo tktk+ return 0信号捕获#!/bin/bashtrap "print_OK" 3function print_OK(){ echo OK}while :do:done发送信号:kill -3 pid屏蔽信号:trap “” 3其他常用内置命令exec command #用command替换当前进程type lsls is aliased to `ls --color=tty`: 空命令while :docmddoneif [ list ]; then : ;else echo false;fi常用工具编辑软件: vi,emacs联机帮助:man, info查找类:find,locate,which,whereis,whatis文本处理类:uniq,cut,paste,join,sort,comm,diff二进制文件读取类:od,xxd,dd,hexdump文本分析类:grep,sed,awk系统状态类:top,ps,pstree,pgrep,/proc,strace,vmstat,netstat传输类:wgetGrep - 全文匹配利器--color 飘红匹配到的部分-i 忽略大小写-v 反向匹配-r 递归匹配文件-o 只打印匹配到的部分-n 打印出行号-c 统计匹配到的行数-w 匹配整词grep "sort“ *.doc Awk – 文本处理利器awk命令的一般形式: awk ' BEGIN { actions } pattern1 { actions } ............ patternN { actions } END { actions } ‘awk -F: '{print $1} END{print "total:",NR}' /etc/passwd Awk – 文本处理利器 (续)取机器序列号dmidecode|awk '/Serial Number:/{print $NF;exit}‘统计词频awk '{a[$0]++}END{for(i in a){print i,a[i]}}' a.txt类似uniq功能awk '! a[$0]++' a.txtAwk – 文本处理利器 (续)杨辉三角#!/usr/bin/awk -fBEGIN { yan[1,0] = 1; for (i = 2; i <= int(ARGV[1]); i++) { yan[i,0] = 1; yan[i,i-1] = 1; for (j = i-2; j > 0; j--) yan[i,j] = yan[i-1,j-1] + yan[i-1,j] } # output for (i = 1; i <= int(ARGV[1]); i++) { for (j = 0; j < i; j++) printf("%d ", yan[i,j]); print }}#Usage:# $ ./test.awk 10head,tail功能:取一个文件的头若干行或者尾部的若干行。常用选项:-n num:指定选取的行数-f:tail的选项,定时输出文件的最后若干行。使用举例tail和head常用来分析日志或者对大规模数据抽取一小部分tail –f example.logwatch -n 1 head url.lst diff,cmp,diff3,sdiff,comm功能:diff:按行比较两个文件的不同cmp:按字节比较两个文件的不同diff3:按行比较三个文件的不同sdiff:输出两个文件的合集。输出文件中两个文件原本的行在同一行中不同列comm:快速的比较两个已经排过序的文件,输出两个文件的合集,交集,或任何单独的部分diff常用选项常用选项。主要介绍diff的各个选项-b 忽略两行行尾空格,以及空格个数的区别-E 忽略tab和空格间的区别-w 完全忽略所有空格类字符-B 忽略空行-I 忽略大小写--normal以normal形式输出不同行。即指输出不同的行-c 以context形式输出不同行。包含不同行的上下文find,locate功能:查找文件。find将在目录树中查找和用户指定模式相符合的文件。locate则是通过在locate的数据库中查找,locate 的数据库由updatedb程序负责维护。常用选项:-name:指定要查找的文件名-perm:指定要查找文件的权限-size:指定要查找文件的大小范围-mtime:指定查找修改时间在n天以内的文件。exec command:将find命令查找到的文件作为command命令的参数使用举例:find . -mtime –1:查找在最近一天内被修改的文件find . -name b.cpp -exec mv \{\} a.cpp \;sort功能:对文件中的各行进行排序。sort排序是根据从输入行抽取的一个或多个关键字进行比较来完成的。缺省情况下以整行为关键字按ASCII字符顺序进行排序。常用选项- m 若给定文件已排好序,合并文件。- c 检查给定文件是否已排好序。- u 对排序后认为相同的行只留其中一行。- d 按字典顺序排序,仅比较字母、数字、空格和制表符。- r 按逆序输出排序结果。- b 在每行中寻找排序关键字时忽略前导的空格和制表符。- t separator 指定字符separator作为字段分隔符。-k,pos1,[pos2]:以pos1到pos2中间的字符为键值使用举例cat words | uniq –c | sort –k 1,1 –n –r 将一批词按照出现频次有高到低排序uniq,join,cut,pastecut功能:用来从标准输入或文本中剪切指定列或者域常用选项:-c:指定剪切字符数-f:field 指定剪切指定域数-d:delimit 指定除空格和tab外的域分隔符使用举例:cut –d : -f 3 example.txtwho –u|cut –c1-8paste功能:将两个文件按行粘贴在不同的列中。是cut的反向操作。dd拷贝二进制文件,格式:count=BLOCKS 只拷贝BLOCKS个数据块ibs=BYTES 一次读入的数据量if=FILE 输入文件obs=BYTES 一次写出的数据量of=FILE 输出文件seek=BLOCKS 输出文件跳过BLOCKS个数据块skip=BLOCKS 输入文件跳过BLOCKS个数据块time dd if=/dev/zero of=test bs=1024k count=1024 查看系统io性能wget功能:支持使用FTP和HTTP协议,从其他主机上下载所需要的文件常用选项:-r:递归的下载目录以及它的子目录和所有文件-nH:不创建以目标主机域名为目录名的目录,将目标主机的目录结构直接下到当前目录下--cut-dir=[number]不在本地机器上建立的目录层数-m, --mirror自动开启适合用来镜像站点的选项 -A, --accept=LIST允许下载的文件类型列表-R, --reject=LIST拒绝继续下载的文件类型列表-D, --domains=LIST允许继续扩展的站点列表--tries=[number]自动重连的次数 -c:断点续传 --debug:使用这个选项可以看到更多wget下载文件过程中的调试信息,比如下载一个http文件时所发送和接收的http包头的格式--timeout=SECONDS控制wget读超时时间,缺省为900秒Wget –nH –cut-dir=1 ftp://*:*@test.baidu.com/wget “http://www.sina.com”参考资料Man正则表达式之道Sed与awkAdvanced Bash-Scripting Guide