近期,为做版图设计的同事设计了3个C shell脚本,以满足他们自动化作业的需求,特记录在此,并对脚本进行讲解。
一、 实例1
1. 问题描述和要求:
- 有一70多万行文件有很多以“wire”开头,以“;”结尾的段
- “ wire”和“;”可能在同一行,也可能之间有多行
- 要求将这样的段中的所有的“n_Logic0_”和“n_Logic1_”删除
- 若有行为“wire n_Logic0_;”或“wire n_Logic1_;”,将整行删除
2. 脚本实现
#!/bin/csh
echo "beginning.."
#取得所有wire所在行的行号,复制给fline变量
set fline = `grep -n 'wire' $1 | sed 's/:.*$//g'`
foreach line ( $fline )
#变量line记录wire所在行的行号,然后寻找封号“;”所在行的行号
set i = $line
echo "$i"
set flag = 0
sed -n "${i}p" ${1} | grep ';$' >& /dev/null
#在下面的程序段中用到了flag变量,来判断是否找到封号“;”,不直接用系统变量status是因为:
#在while循环外无法看到while循环内的status变量值的变化,所有while后的括号中,不能直接用表达式:$status == 1
if ( $status ) set flag = 1
while ( $flag == 1 )
@ i = $i + 1
set flag = 0
sed -n "${i}p" ${1} | grep ';$' >& /dev/null
if ( $status ) set flag = 1
end #在while循环结束后,变量i存有封号所在行的行号,用sed命令即可开始处理行 $line 和 行 $i 之间的内容
sed -i -r "${line},${i}s/n_Logic(0|1)_[[:blank:]]*,[[:blank:]]*|,[[:blank:]]*n_Logic(0|1)_[[:blank:]]*|wire[[:blank:]]*n_Logic(0|1)_[[:blank:]]*;//g" ${1}
end #end of foreach;循环处理每个wire段
二、实例2
1. 问题描述和要求:
- 某指定目录下有若干文件
- 要求根据每一个文件的文件名生成对应的一个可执行文件
- 亦即目录下文件数与生成的可执行文件数相同
- 存在一文件(streamin)
- 每一个要生成的可执行文件,可以先复制streamin的内容,再用上述的指定目录下的文件的文件名替代其中的部分字符串即可
- 用参数传递目录名,(存在的文件streamin也用参数传递)
- 目录下文件都以".gds" 结尾,应去除该结尾目录下另有一文件:lngds.csh,应不考虑该文件
- 生成的可执行文件放到output目录下 ,该目录与脚本在同一目录下
- 生成的可执行文件以“streamin+序号”命名,如streamin1
- 生成的可执行文件,用户和用户组具有可执行权限
#!/bin/csh
#Usage: ./scriptname directoryname filename
echo "Begin..."
#将目录$1下的文件的文件名(除去lngds.csh)赋值给变量filenamelist
set filenamelist = `ls ${1} | grep -v 'lngds.csh'|sed 's/\.gds//g'`
#设置输出目录名为output
set outputname = "output"
set i = 1
foreach filename ( $filenamelist )
#先将文件$2的内容复制出来生成文件streamin$i
cat ${2} > $outputname/streamin$i
#再将生成的文件的部分内容用$1目录下的文件名字替换
sed -i -r "s/RAM_DP_16*960/$filename/g" $outputname/streamin$i
#给生成的文件的用户、用户组加上可执行权限
chmod u+x,g+x $outputname/streamin$i
@ i = $i + 1
end
echo "Finished~~~"
三、实例3
1. 问题描述和要求
- 有一指定文件,要求对其中所有以“.subckt”(不区分大小写)开头的行进行格式处理
- 处理结果保存到新文件中
.subckt An_S v0 v2
fkdfkd
.subckt An_T a b c
对第1、3行处理,结果为:
XI1 net1 net2 / An_S
XI2 net3 net4 net5 / An_T
行处理规则即:
- 第一个字段“ .subckt”用“XI序号”代替
- 第二个字段放到行尾,并在其前加上“/”和“空格”
- 剩下的字段全部用“net数字”代替放在新文件相应行“XI序号”和“/”之间
- 整个新文件中所有“net”后的数字不能有重复
- 脚本设计的关键是awk命令的用法。需要注意的是,awk命令引用外部脚本定义的变量,其引用格式为:" ' $varname' "。
- 脚本前面的代码增强了用户体验。
#!/bin/csh
#Program:
#Scriput name: yzx.csh
#Usage: ./yzx.csh filename or ./yzx.csh
#History:
#2012-05-09 By Adultf
if ( $#argv == 1 ) then
set filename = $1
else if ( $#argv == 0 ) then
echo "The script should be executed as: ./yzx.csh filename!"
echo "But it doesn't matter, you can enter the file name now."
echo -n "Please enter the file name:"
set filename = $<
else if ( $#argv > 1 ) then
echo "The script should be executed as: ./yzx.csh filename!"
echo "But the argument is more than 1."
echo "Terminate script execution!"
exit
endif
if ( ! -e $filename ) then
echo "The file doesn't exist!"
echo "Terminate script execution!"
exit
endif
set fline = `grep -n -i '\.subckt' $filename | sed 's/:.*$//g'`
set i = 1
set sumk = 0
if ( -e output && -f output ) then
echo -n "The ouput file has existed! Delete?(y/n)"
set answer = $<
if ( $answer == 'y' || $answer == 'Y' ) then
echo "Delete existed output file!"
rm -f output
else
echo "You choose not to delete the existed output file."
echo " You may want to have a check."
echo "So, terminate script execution!"
exit
endif
endif
echo "Create new output file!"
echo "Beginning..."
foreach line ( $fline )
if ( -e output ) then
awk 'NR=="'$line'"{printf "%s%i\t","XI","'$i'";j=2;k=1;while (j<NF) {printf "%s%i\t","net",k+"'$sumk'";j++;k++};printf "/\t"$2"\n"}' $filename >> output
else
awk 'NR=="'$line'"{printf "%s%i\t","XI","'$i'";j=2;k=1;while (j<NF) {printf "%s%i\t","net",k+"'$sumk'";j++;k++};printf "/\t"$2"\n"}' $filename > output
endif
@ i = $i + 1
set temp = `sed -n "${line}p" $filename | wc -w`
@ temp = $temp - 2
@ sumk = $sumk + $temp
end #end of foreach
echo "Finished~~~"