c语言sscanf函数的用法是什么
269
2022-11-29
shell编程 (3) —— 调试
shell调试技巧
shell脚本虽然不像高级语言那样有专门的调试工具和调试机制,但是前辈们仍然想出了一些办法来进行shell脚本的错误检测。
trap
shell脚本在执行的时候会产生三伪信号(不是操作系统发出的信号)。我们可以使用trap捕获信号然后进行shell的调试。 shell伪信号的产生:
信号 | 产生条件 |
EXIT | 正常退出 |
ERR | 返回非零状态码 |
DEBUG | 命令执行之前 |
trap的使用: trap commaond sig1,sig2,… 注:command使用单引号”’”包围的。 例子: code:
#!/bin/bashtrap 'echo "the $LINENO line before executing, a is $a"' DEBUGtime=0a=1while (( $time<6 ))do let "a=a*2" let "time++"done
output:
$ ./two.shthe 3 line before executing, a isthe 4 line before executing, a isthe 5 line before executing, a is 1the 7 line before executing, a is 1the 8 line before executing, a is 2the 5 line before executing, a is 2the 7 line before executing, a is 2the 8 line before executing, a is 4the 5 line before executing, a is 4the 7 line before executing, a is 4the 8 line before executing, a is 8the 5 line before executing, a is 8the 7 line before executing, a is 8the 8 line before executing, a is 16the 5 line before executing, a is 16the 7 line before executing, a is 16the 8 line before executing, a is 32the 5 line before executing, a is 32the 7 line before executing, a is 32the 8 line before executing, a is 64the 5 line before executing, a is 64
这种调适技巧针对递归的作用是有限的: code
trap 'echo "the $LINENO line before executing, a is $a, b is $b"' DEBUGa=120b=250gcd(){ if [ $b -eq 0 ]; then return $a else t=$a a=$b b=`expr $t % $b` gcd $a $b fi}gcd $a $becho "gcd is "$
执行代码
$ ./trap.shthe 3 line before executing, a is , b isthe 4 line before executing, a is 120, b isthe 15 line before executing, a is 120, b is 250the 16 line before executing, a is 10, b is 0gcd is 10
试试ERR: code:
#!/bin/bashtrap 'echo "focus on $LINENO,"$string' ERRstring="here is a error"
执行脚本: (我们将标准错误输出重定向到文件file中)
$ ./trap.sh >&2 2>filefocus on 4,here is a error$ cat file./trap.sh: line 4: ipconfig: command not found
tee
有关tee的解释是这样的: tee - read from standard input and write to standard output and files tee读入数据,然后产生两支分流,一支是标准输出,另一支输出数据到文件。 一个例子: 查阅本机eth0的mac地址。 它可以用这条语句实现: cat /etc/sysconfig/network-scripts/ifcfg-eth0 |grep HWADDR |cut -d= -f2 但是,这看起来有些复杂。。。 我们可以使用tee来跟踪流。 cat /etc/sysconfig/network-scripts/ifcfg-eth0 | tee -a txt| grep HWADDR |tee -a txt | cut -d= -f2 | tee -a txt 运行结果:
$ ./tee.sh00:0c:29:e8:97:1b$ cat txtDEVICE=eth0HWADDR=00:0c:29:e8:97:1bTYPE=EthernetUUID=c5857400-a96d-451d-8983-10a52193427cONBOOT=noNM_CONTROLLED=yesBOOTPROTO=dhcpIPADDR=192.168.137.99NETMASK=255.255.0.0IPV6INIT=noUSERCTL=noHWADDR=00:0c:29:e8:97:1b00:0c:29:e8:97:1b
调试钩子
调试钩子的思想有些像C中的条件编译。当我们需要进行中间变量的输出时打开它,否则关闭它。 shell中的调试钩子的格式一般是这样的:
DEBUG(){ if [ "$DEBUG" = "true" ]; then ...
还是那个2^6的例子:
DEBUG(){ if [ "$DEBUG" = "true" ]; then echo "time is $time, a is $a" fi}time=0a=1while (( $time<6 ))do let "a=a*2" let "time++" DEBUG done
执行脚本:
$ export DEBUG="true"; ./debug.sh time is 1, a is 2time is 2, a is 4time is 3, a is 8time is 4, a is 16time is 5, a is 32time is 6, a is 64
shell选项
选项名称 | 简写 | 意义 |
noexec | n | 语法检验,不执行命令 |
xtrace | x | 执行每一条命令之前将命令打印出来 |
没有 | c… | 从…读取命令 |
直接使用指令sh也就是使用bash - GNU Bourne-Again SHell 他们的手册查询结果是一样的。
[edemon@CentOS ~]$ man sh > sh.txt[edemon@CentOS ~]$ man bash > bash.txt[edemon@CentOS ~]$ diff bash.txt sh.txt[edemon@CentOS ~]$
例子:
echo I start to run....if [ 1 -lt 2 ] then echo yesfi
[edemon@CentOS ~]$ ./err.sh I start to run...../err.sh: line 4: syntax error near unexpected token `fi'./err.sh: line 4: `fi'[edemon@CentOS ~]$ bash -n err.sh err.sh: line 4: syntax error near unexpected token `fi'err.sh: line 4: `fi'[edemon@CentOS ~]$ sh -n err.sh err.sh: line 4: syntax error near unexpected token `fi'err.sh: line 4: `fi'
仍然以2^6的我例子来做说明:
#!/bin/bashtrap 'echo "the $LINENO line before executing, a is $a"' DEBUGtime=0a=1while (( $time<6 ))do let "a=a*2" let "time++"done
add -x to run our program: 在普通语句前面加上’+’,变量已经更新。 在trap debug前面加上“++”
$ bash -x trap_debug.sh + trap 'echo "the $LINENO line before executing, a is $a"' DEBUG++ echo 'the 3 line before executing, a is 'the 3 line before executing, a is + time=0++ echo 'the 4 line before executing, a is 'the 4 line before executing, a is + a=1++ echo 'the 5 line before executing, a is 1'the 5 line before executing, a is 1+ (( 0<6 ))++ echo 'the 7 line before executing, a is 1'the 7 line before executing, a is 1+ let 'a=a*2'++ echo 'the 8 line before executing, a is 2'the 8 line before executing, a is 2+ let time++++ echo 'the 5 line before executing, a is 2'the 5 line before executing, a is 2+ (( 1<6 ))++ echo 'the 7 line before executing, a is 2'the 7 line before executing, a is 2+ let 'a=a*2'++ echo 'the 8 line before executing, a is 4'the 8 line before executing, a is 4+ let time++++ echo 'the 5 line before executing, a is 4'the 5 line before executing, a is 4+ (( 2<6 ))++ echo 'the 7 line before executing, a is 4'the 7 line before executing, a is 4+ let 'a=a*2'++ echo 'the 8 line before executing, a is 8'the 8 line before executing, a is 8+ let time++++ echo 'the 5 line before executing, a is 8'the 5 line before executing, a is 8+ (( 3<6 ))++ echo 'the 7 line before executing, a is 8'the 7 line before executing, a is 8+ let 'a=a*2'++ echo 'the 8 line before executing, a is 16'the 8 line before executing, a is 16+ let time++++ echo 'the 5 line before executing, a is 16'the 5 line before executing, a is 16+ (( 4<6 ))++ echo 'the 7 line before executing, a is 16'the 7 line before executing, a is 16+ let 'a=a*2'++ echo 'the 8 line before executing, a is 32'the 8 line before executing, a is 32+ let time++++ echo 'the 5 line before executing, a is 32'the 5 line before executing, a is 32+ (( 5<6 ))++ echo 'the 7 line before executing, a is 32'the 7 line before executing, a is 32+ let 'a=a*2'++ echo 'the 8 line before executing, a is 64'the 8 line before executing, a is 64+ let time++++ echo 'the 5 line before executing, a is 64'the 5 line before executing, a is 64+ (( 6<6
bash -c 让我们从字符串中读取命令。
$ bash -c "echo \"hello world\""
shell的内部变量: |变量名|意义| |LINENO|行号| |FUNCNAME|函数数组| |ps4|设置提示格式|
练习
codingame —— Onboarding
大意:外星飞船来了,每一轮都有两只飞船向我们袭来,我们需要击毁最近的那个。
# CodinGame planet is being attacked by slimy insectoid aliens.# <---# Hint:To protect the planet, you can implement the pseudo-code provided in the statement, below the player.# game loopwhile true; do # enemy1: name of enemy 1 read enemy1 # dist1: distance to enemy 1 read dist1 # enemy2: name of enemy 2 read enemy2 # dist2: distance to enemy 2 read dist2 # Write an action using echo # To debug: echo "Debug messages..." >&2 if [ $dist1 -lt $dist2 ]; then result=${enemy1} else result=${enemy2} fi # You have to output a correct ship name to shoot ("Buzz", enemy1, enemy2, ...) echo $resultdone
codingame —— Temperatures
大意:给出n个气温,求出最接近0的温度。如果有一正一负都最接近0摄氏度,那么输出正整数。
注意下面字符串拆分成数组,求解整数绝对值的方法。
# Auto-generated code below aims at helping you parse# the standard input according to the problem statement.# n: the number of temperatures to analyseread n# temps: the n temperatures expressed as integers ranging from -273 to 5526read tempsarray=(${temps// / }) #(${temps//,/ })表示以逗号拆分dis=6000ans=0for val in ${array[@]}; doif [ ${val#-} -lt $dis ]; thenans=$valdis=${val#-}elif [[ ${val#-} -eq $dis && $val -gt 0 ]]; thenans=$valfidone# Write an action using echo# To debug: echo "Debug messages..." >&2echo $ans
codingame —— ASCII Art
大意: 输入L,H,old_string, 英文字符表示符。 输出old_string对应的新表示符。 比如:
input45 E # ## ## ## ### ### ## # # ### ## # # # # # ### # ## # ## ## ### # # # # # # # # # # ### ### # # # # # # # # # # # # # # # # # ### # # # # # # # # # # # # # # # # # # # # # # # # ### ## # # # ## ## # # ### # # ## # ### # # # # ## # # ## # # # # # # ### # # # ## # # # # # # # # # # # # # # # # # # # # # # # # # # ## # # # # # # # # ### # # # # # # ## ## ## ### # ## # # ### # # # ### # # # # # # # # # ## # ### # # # # # # ### # Output### # ## # ###
访问字符串中的单个字符,自己暂时仅想到这样的办法:
str="ABCDEF"echo ${#str}for ((i=0;i<${#str};i++)); doecho -e ${str:$i:1}'\c'doneecho ""
[edemon@CentOS workspace]$ ./test.sh6ABCDEF
自己一开始使用C写了一个:
#include 然后再尝试用bash来写,但是有一个问题,怎么进行两个英文字符的相减操作?字母转成整数?可是怎么转? # Auto-generated code below aims at helping you parse# the standard input according to the problem statement.read Lread Hread Tstring=""for (( i=0; i 打印九九乘法表 for (( i=1;i<10;i++ )); do for (( j=1;j<=i;j++ )); do echo -e $j" * "$i" = "`expr $j \* $i`"\t\c" done echo ""done 在test下创建30个目录,并赋予所有者读、写、可执行执行的权限,同组其他人员读、可执行权限,其他人员读的权限。 for (( i=1;i<=30;i++ ));domkdir -p ./test/dir$ichmod -R 754 ./test/dir$idonels -l
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~