学习shell编程两周小记
两个星期前,我对shell编程一无所知,
两个星期后的现在,虽然离精通还差得很远,但是我已经能写一些shell脚本来帮助我使用linux了(我用的ubuntu10.04),
回顾这两个星期,我使用windows和使用ubuntu的时间大概是1:3,
心情好的时候(完成老师布置的task1),我会给VIM装插件玩(下图是我现在的VIM,目前还很满意),
心情烂的时候(写不出task2),我一天就吃一顿饭...
因为之前linux用的少,所以我得去补学很多命令的使用方式,比如强大的sed和awk
我每天大概花2小时左右练习shell,因为还有别的课,这已经我的极限了,
我看完了《鸟哥的Linux私房菜》的十到十三章《学习shell和shell script》,很不错的入门系列^_^,
我练习了其中的示例代码,感觉差不多懂了,就满怀信心地开始做作业,
结果,哼哼,
现实远比想象的残酷多了,更何况shell编程又充满了陷阱,
最后,完成task2的那200行代码的脚本,花了我将近20个小时T^T
不经历风雨,怎能见彩虹!
不过现在看着自己的代码,还是很有成就感的,哈哈o(∩∩)o...。
最后晒下我的task2的代码,这个脚本是用来显示指定目录下所有文件的相同行的,欢迎高手指点。
如果你也在学linux,欢迎与我交流^_^
1 #!/bin/bash
2 #Program:
3 # Check same line in different files
4 # Usage:command [选项] ... 目录名
5 # 选项:
6 # -p: print which line have been included by which files
7 # -e [文件名]: extract duplicated line to a specified file
8 # -r: remove duplicated line in the file which include it
9 #History:
10 #2011/10/26 gaodayue First release
11 PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
12 export PATH
13
14
15 usage="Usage: $0 -[per] DirectoryName"
16 workingdir=$(pwd) # 当前的目录名
17 directoryname="" # 检索的目录名
18 temp_file=${workingdir}"/.files" # 存放检索目录下的文件名
19 sameline_file=${workingdir}"/.sameline" # 存放相同行的文件
20 havesameline_file=${workingdir}"/.havingsameline" # 存放拥有相同行文件名的文件
21 touch $temp_file
22 touch $sameline_file
23 touch $havesameline_file
24
25 # check if $1 is a directory and can read
26 check_directory(){
27 # if $1 is a directory?
28 [ ! -d $1 ] && echo "ERROR: '$1' is not an directory!" && exit 1
29 # can we enter the directory?
30 [ ! -r $1 -o ! -x $1 ] && echo "ERROR: DO NOT have the Permission to enter the '$1' directory!" && exit 1
31 directoryname=$1
32 }
33
34
35 parse_same_line(){
36 cd $directoryname
37 # 得到目录下的文件名
38 files=$(ls -l | awk '$8!="" && $1~/^-/{printf $8 ""} ')
39 # 将文件名保存到.files文件下
40 echo $files > $temp_file
41 # 得到目录下文件的个数
42 file_num=$(cat $temp_file | wc -w)
43
44 # 对这些文件进行两两比较相同的行
45 # 相同的行存入.sameline文件中
46 # 拥有相同行的文件名存入.havesameline文件的对应行中
47 # 比如:
48 # .sameline文件:
49 # line1
50 # line2
51 # .havesameline文件:
52 # 1.txt 2.txt
53 # 2.txt 3.txt
54 # 表示
55 # 1.txt和2.txt拥有相同行line1
56 # 2.txt和3.txt拥有相同行line2
57
58 # 两两循环比较
59 i=1
60 while [ $i -lt $file_num ]
61 do
62 file1=$(cat $temp_file | cut -d ' ' -f $i)
63 j=$(($i+1))
64 while [ $j -le $file_num ]
65 do
66 file2=$(cat $temp_file | cut -d ' ' -f $j)
67 samelines=$(grep -Fxf $file1 $file2) # 得到两个文件所有的相同行
68 IFS_OLD=$IFS
69 IFS="
70 "
71 for sameline in $samelines
72 do
73 $(grep -xq "$sameline" $sameline_file) # 在.sameline文件中查找该行
74 if [ $? -eq 0 ];then
75 # 若.sameline文件中已经有该行
76 # 得到该行的行数
77 linenum=$(grep -xn "$sameline" $sameline_file | sed 's/:.*//')
78 # 取得.havesameline文件中对应行数的内容,即包含该行的文件
79 oldcontent=$(cat $havesameline_file | head -n $linenum | tail -n 1)
80 $(echo $oldcontent | grep -wq "$file2") # 查找包含该相同行的文件名中有没有file2
81 if [ $? -ne 0 ];then
82 # 若包含该行的文件名中还没有file2,则加入file2
83 newcontent=${oldcontent}' '$file2
84 $(sed -i "${linenum}s/.*/${newcontent}/" $havesameline_file)
85 fi
86 else
87 # 若.sameline文件中还没有该行
88 # 增加该行,并在.havesameline文件中添加这两个文件名
89 echo $sameline >> $sameline_file
90 echo ${file1}' '${file2} >> $havesameline_file
91 fi
92
93 done
94 IFS=$IFS_OLD
95 j=$(($j+1))
96 done
97 i=$(($i+1))
98 done
99 # 回到工作目录
100 cd $workingdir
101 # 删除用于临时存储文件名的.files文件
102 $(rm $temp_file)
103 }
104
105 # 解析完成后,删除.sameline与.havingsameline文件
106 # 该函数与parse_same_line成对出现
107 end_parse(){
108 $(rm $sameline_file)
109 $(rm $havesameline_file)
110 }
111
112 # -p: print same lines
113 printsameline(){
114 # 解析相同行
115 parse_same_line
116 # 如果没有相同行,提示信息并返回
117 [ $(cat "${sameline_file}" | wc -l) -eq 0 ] && echo "No same line Found!" && return 0
118 # 否则,输出结果
119 linenum=1
120 while read line
121 do
122 # 根据行号得到有这行的文件名
123 thefiles=$(cat "${havesameline_file}" | head -n $linenum | tail -n 1)
124 # 文件数
125 thefilesnum=$(echo $thefiles | wc -w)
126 # 输出
127 echo "${line}\nis included in ${thefilesnum} files"
128 for item in $thefiles
129 do
130 echo "${item}"
131 done
132 echo ""
133 linenum=$(($linenum+1))
134 done < "$sameline_file"
135 # 结束解析
136 end_parse
137 }
138
139 # -e [文件名]: extract duplicated line to a specified file
140 extract(){
141 # $1为指定要输出的文件
142 if [ -e $1 ];then
143 # $1存在,但不是文件,提示出错
144 [ ! -f $1 ] && echo "ERROR: '$1' EXISTS but IS NOT a file" && return 1
145 # $1存在,且为文件,让用户选择是否继续?
146 while [ "${isContinue}" != 'y' -a "${isContinue}" != 'n' ]
147 do
148 read -p "'$1' exists, continue will replace its content.Continue?(y/n):" isContinue
149 done
150 if [ "${isContinue}" = 'y' ];then
151 # 判断对该文件是否有写权限
152 [ ! -w $1 ] && echo "DO NOT have the WRITE PERMISSION to file '$1'" && return 1
153 # 有写权限,则将-p的执行结果写入文件
154 printsameline > $1
155 else
156 return 0
157 fi
158 else
159 # $1不存在,则创建
160 touch $1 2> /dev/null
161 # 创建失败,则提示信息
162 [ $? -ne 0 ] && echo "CAN NOT CREATE the file '$1'" && return 1
163 # 创建成功,则将-p的执行结果写入文件
164 printsameline > $1
165 fi
166 }
167
168 # -r: remove duplicated line in the file which include it
169 remove(){
170 # 执行解析
171 parse_same_line
172 # 处理解析结果
173 linenum=1
174 while read line
175 do
176 # 根据行号得到有这行的文件名
177 thefiles=$(cat "${havesameline_file}" | head -n $linenum | tail -n 1)
178 # 在每个文件中删除该行
179 for item in $thefiles
180 do
181 item_fullname="${directoryname}/${item}"
182 # 删除item_fullname文件中line这行
183 $(sed -i /"^${line}$"/d ${item_fullname})
184 done
185 linenum=$(($linenum+1))
186 done < "$sameline_file"
187 # 结束解析
188 end_parse
189 }
190
191 # 检查参数
192 case $1 in
193 "-p")
194 [ $# -ne 2 ] && echo $usage && exit 1
195 check_directory $2
196 printsameline
197 ;;
198 "-e")
199 [ $# -ne 3 ] && echo $usage && exit 1
200 check_directory $3
201 extract $2
202 ;;
203 "-r")
204 [ $# -ne 2 ] && echo $usage && exit 1
205 check_directory $2
206 remove
207 ;;
208 *)
209 echo $usage;exit 1
210 ;;
211 esac
212
213 exit $?