提示:用户画像为
linux用户
和ICer
、需要使用tcsh
、bash
进行编程来完成日常的工作的各个读者,旨在帮助用户学以致用。
文章目录
一、前言:IC设计中的Linux shell
提示:下文是ic设计、或使用到linux多种shell下的工作者的一些知识。
IC design (integrated circuit design): 集成电路设计,可以抽象化理解成将预设的功能设计进行物理实现的过程。IC design百度词条
在ic设计的工作中,我们会用到很多的EDA (Electronic design automation)工具,帮助完成设计和实现过程,还有文本编辑的工具等,这些工具都是在linux系统环境下工作的。起初那些EDA工具是在Unix上运行的,但是后期Linux开源的优势占据了上风,有着大量的开源的工具可供EDA厂商使用,当然Linux系统本身有着很强的稳定性等,逐渐的EDA工具也就转移到了Linux系统上了。
Linux系统是依靠shell进行交互的,不同shell往往有着不同的语法规则、不同的bulit-in命令和其用法等。现如今最常见的Linux shell包括tcsh(从csh发展来的)、bash(从shell发展来的)、ksh(兼容csh和sh的优势)、dash(从shell发展而来,和bash很接近)、zsh(集成tcsh和bash的各自的优势)等。
ICer工作者留心的话,可能就会注意到用前辈们大都使用的是tcsh(或者csh)和bash(年代久远的大厂可能还有一部分sh脚本)。使用过tcsh和bash的shell的用户都知道,bash脚本是可以定义函数的,相对于tcsh这是一个很大的优势,还有bash是可以支持复杂的数据结构的,这一点也是tcsh shell不具备的(你可能看到多处、或者百度AI等告知,bash不支持hash,但实际上bash是支持的)。
例子:使用bash shell定义复杂的数据结构
## shell is bash
[weifexie@atletx7-neu004 ~/shell_tra]$ echo $0
bash
## define hash
[weifexie@atletx7-neu004 ~/shell_tra]$ xie[wei]='feng'
[weifexie@atletx7-neu004 ~/shell_tra]$ echo ${xie[wei]}
feng
## define list
[weifexie@atletx7-neu004 ~/shell_tra]$ xiexie=(1 2 3 4)
[weifexie@atletx7-neu004 ~/shell_tra]$ echo ${xiexie[0]}
1
可能是tcsh脚本中不能定义函数,ICer工作者可能会看到大量的.csh脚本在不断的source,一个工作需要调用大量的.csh脚本。如果换成bash脚本就不需要这样子做了,直接在bash脚本内部直接定义函数,将脚本集成到一起。
如此看来,bash比tcsh在运用上更具有优势才对,但为什么tcsh却是ICer使用最多的shell呢?为什么不将bash换成默认的shell呢?
四下询问、查看资料、同行答疑、文本记载、野史等,可能的原因有:
- tcsh在bash前定版发行,在bash没有发行前,ICer在csh上工作,累计了大量的代码,csh和bash不兼容,代码的重新编写的工作量很大,同时IC行业是一个需要迭代升级的行业,代码往往会在原有的基础上进行升级,先入为主了。有经历的人说到:有段时间ICer在solaris 7和solaris8上做IC designs,csh是默认的shell,同时还不支持bash,如果想支持bash需要另外安装GNUBash。
- 从linux的发展史可以了解到,ICer起初是在unix上完成工作的,很长的一段时间,sh是用来编程,csh用来做交互式设计,在那时,csh相对于sh来说有着很多的优势,有着更多的功能,对用户更友好,可能从那时开始ICer想要完成工作,学习csh要比sh更为有用。再后来bash定版发行,取代了sh成为了现在诸多Linux的默认shell,但留心你会发现,ICer的工作shell可能依然还是tcsh。
Tcl、Perl、Python等脚本语言相比于tcsh、bash等,可以帮助ICer完成更为复杂的流程和过程,是ICer工作者继掌握tcsh和bash后必须要知晓的语言了,Tcl、Perl、Python后续会介绍各自的用法和案例,旨在帮助读者可以使用该知识实现设计工作的自动化。
提示:以下是本篇文章正文内容,下面案例可供参考
二、tcsh语法、bash语法 、zsh语法
tcsh语法和bash语法不兼容,这里提醒一下,二者作为shell时,built-in命令很多都是相同的,用法也可能是相同的,因为这两者再最初的阶段都是从sh处继承了很多底层的内容,但是作为编程语言时,二者就有着很大的差别了。zsh语言可以看作是tcsh和 bash的集成。以下介绍tcsh、bash、zsh在作为编程语言时的用法。
在此处笔者给出两个相同的脚本,只是一个是tcsh语言书写的,另一个是bash语言书写的。读者可以对照就可以知道二者之间的区别了。在脚本之后,该文总结tcsh的bash的语言特点。
案例
tcsh语言编写的脚本
读者可以不用在意脚本具体实现了什么功能,只需掌握语法规则即可。
# !/usr/bin/tcsh
# this used to atgp part and it would be better if used ~/shell_tra/atpgsim_auto.csh
# usage: $0 regr_fl which_mode(s)
#
if ($#argv < 2 || $1 =~ *"help"*) then
echo "pls chk usage and follow the format below\
$0 regr_fl which_mode\
eg: ~/shell_tra/run_atpg.csh usb4_sc0_t_nldrel/ stac \
results: regr_fl is: usb4_sc0_t_nldrel/; mode(s) you chosen: (wc: 3) scm_STAC0 scm_STAC1 scm_STAC2"
exit 1
else
# get now_path where script is running
set now_path = `pwd`
echo -n "\nregr_fl is: $1; mode(s) you chosen: "
if (! -d $1) then
echo "pls chk $1, and its validity"
exit 1
else
set path_regr_fl = $now_path/$1
shift
set session_lists = ()
foreach arg($argv)
if(-d $path_regr_fl/atpg/session/) then
set findfd = `find $path_regr_fl/atpg/session/ -iname "*$arg*" -type d`
# get findfd name
foreach findfd_name($findfd)
set findfd_name = `basename $findfd_name`
set session_lists = ($session_lists $findfd_name)
end
else
echo "$path_regr_fl/atpg/session/ is non-exist, "
endif
end # foreach arg
echo -n "(wc: $#session_lists) $session_lists" # cont. mode(s) you chosen: (wc: $#session_lists) $session_lists
endif
endif
echo
# main function start
# foreach session_lists
foreach sess($session_lists)
echo "//performing sess ($sess) mode//"
# cd $1/atpg/session/$sess
cd $path_regr_fl/atpg/session
# ls -d *$sess*
set sess_modes = `ls -d *$sess* | awk '{print $NF}'`
foreach mode($sess_modes)
cd $mode
# run atpg csh
gnome-terminal --tab --title "$mode" -- csh -c "echo `pwd`;./run" &
wait
cd -
end
cd $path_regr_fl/atpg/session
end # foreach sess
exit 0 # end successfully
改用bash语言编写上述code
#!/usr/bin/bash
# this bash script is transformed from ~/shell_tra/run_atpg.csh
#
if [ $# -lt 2 ];then
# cat EOF inf
echo "psl chk usage and follow the format below
$0 regr_fl which_mode
eg: ~/shell_tra/atpg_run.bash usb4_sc0_t_nldrel stac
results: regr_fl is: usb4_sc0_t_nldrel; mode(s) you chosen: (wc: 3) scm_STAC0 scm_STAC1 scm_STAC2"
exit 1
else
# get now_path where script is running
now_path=`pwd`
echo -n "rer_fl is: $1; mode(s) you chosen: "
if [ ! -d $1 ]; then
echo "pls chk $1, and its vailidity"
exit 1
else
path_regr_fl="$now_path/$1"
#echo path_regr_fl="$now_path/$1"
shift
session_lists=()
for arg in $@; do
#echo "\$@ = $@, arg = $arg"
if [ -d $path_regr_fl/atpg/session/ ]; then
findfd=`find $path_regr_fl/atpg/session/ -iname "*$arg*" -type d`
# echo "findfd=$findfd"
# get findfd name
for findfd_name in ${findfd[@]}; do
#echo "findfd_name=$findfd_name"
findfd_name=$(basename $findfd_name)
session_lists=("${session_lists[@]}" "$findfd_name")
#echo "session_lists=${session_lists[@]}"
done
else
echo "$path_regr_fl/atpg/session is non-exist"
fi
done
echo -n "(wc: ${#session_lists[@]}) ${session_lists[@]}" #
fi
fi
echo
# main function start
# for in session_lists
for sess in ${session_lists[@]}; do
echo "//performing sess ($sess) mode//"
# cddir $1/atpg/$sess
cd $path_regr_fl/atpg/session
# ls -d *$sess*
sess_modes=`ls -d *$sess* | awk '{print $NF}'`
for mode in ${sess_modes[@]}; do
cd $mode
# run atpg csh
gnome-terminal --tab --title "$mode" -- csh -c "./run; exec tcsh" &
sleep 5s
cd -
done
cd $path_regr_fl/atpg/session/
done
exit 0
1、注释和shebang
# tcsh
# 注释使用#号
# shebang -- #!/usr/bin/tcsh
# (注意:第一行shebang可以省略不写,那么,脚本使用默认shebang,即当前命令行$SHELL)
# bash
# 注释符使用 #
# shebang -- #!/usr/bin/bash
# 省略不写的情况同上
2、变量定义和引用
# tcsh
# 定义字符变量
set now_path = `pwd`
# 定义列表
set session_lists = (1 2 3 4)
# 注意:tcsh定义变量时,变量名、等号、等号右边的内容之间都是有空格的
# 列表元素的引用
# session_lists 第二个元素:$session_lists[2]
# bash
# 定义字符变量
now_path = `pwd`
# 定义列表
session_lists=(1 2 3 4)
# 注意:bash定义变量时,变量名、等号、等号右边的内容之间都是没有空格的
# 列表元素的引用
# session_lists 第二个元素:${session_lists[1]}
# 注意:bash中列表的索引从0开始,tcsh是从1开始的
3、条件判断
# tcsh
# if 条件判断
if ($#argv < 2 || $1 =~ *"help"*) then
echo
else
echo
endif
# if 后是小括号,小括号和括号内的内容之间可以有、也可以没有空格
# bash
if [ $# -lt 2 ];then
echo
else
echo
fi
# if 和之后的中阔号需要有空格,中括号和括号内的内容之间也需要有空格
# if的条件不满足时的分支else语言,当else存在时,else分支就不能没有语句,否则会出错,如
if [ ]; then
echo
else
fi
# 上else分支不能是空语言,这样会出错
4、结构控制
# tcsh
foreach sess($session_lists)
echo
end
# bash
for sess in ${session_lists[@]}; do
echo
done
5、函数
# tcsh
# 不支持函数功能
# bash,
function sum(){
return $(($1+$2))
}
sum 3 4
echo "sum = $?"
6、参数变量
# tcsh
# $#argv -- 表示参数个数
# $argv -- 表示参数列表
# $argv[1] --表示第一个参数,从1开始,同$1
# $0 -- 脚本名称
# bash
# $# -- 表示参数个数
# $@ -- 表示参数列表
# $1 -- 表示第一个参数
# $0 -- 脚本名称
7、引用dirname、basename
# tcsh
# set findfd_name = `basename $findfd_name`
# 使用``反引号来引用basename、dirname得到的结果
# bash
# findfd_name=$(basename $findfd_name)
# 使用$符号引用
8、附加文本tcsh语法word文档
以上是tcsh和bash基于上脚本所表现出来的在语法上的不同,上述基础语法也许就可以帮读者完成一些基本的进程了,当然,掌握tcsh、bash、和zsh语法于胸,笔者该文是远远不够的,故附上tcsh的语法文档,旨在帮助大家全面掌握tcsh,同时在该本第三部分附上了多个shell的文档,供读者自研。
zsh用法结合了tcsh和bash的二者的优势,该文不再赘述,第三部分可以找到zsh的语法。
三、相关资料
-
bash – 菜鸟教程
-
GNU – Bash参考手册
-
tcsh IBM Tcsh shell变量
tcsh - unix, linux command -
zsh – 池建强的zsh的介绍、安装和配置
本文参考文献和同行笔墨
IC设计中Linux shell的选择和使用(bash、tcsh、zsh)
附上tcsh语言word文档
四、总结
该文介绍了在ICer设计中常用的tcsh,另一种linux默认的bash shell。给出了一个案例,使用tcsh和bash书写,由此案例总结了tcsh和bash的语法区别,附上tcsh、bash、和zsh的多份学习材料,旨在帮助读者全面的学习。
念念不忘,必有回响
END