13章shel script习题答案

简介:

    因为感觉对Linux命令还没有多大的感觉,所以就专门找了鸟哥的书来看一下,折腾了几天看基础篇的shell部分,收获还是蛮大的,至少对Linux命令是有点感觉了,然后往前学习的一些知识,在理论知识方面也得到了一定的扩充了。先不多说,把习题的答案分享一下。


《鸟哥的Linux私房菜》基础篇P398习题


(1)请新建一个script,当你执行该script的时候,该script可以显示你目前的身份(用whoami)和你目前所在的目录(用pwd)。

这道题的答案已经直接给出了,直接上脚本:

1
2
3
4
5
6
7
8
#!/bin/bash
# Program:
#       Showing who you are and where you are.
# History:
#        2015 / 07 / 26       XPleaf  First release
PATH=$PATH:~/bin
export PATH
echo  "the user is '$(whoami)',and you are in '$(pwd)'"

执行结果:

1
2
[root@moban test]# sh sh01.sh 
the user  is  'root' ,and you are  in  '/root/scripts/test'

(2)请自行写一个程序,该程序可以用来计算我还有几天可以过生日。

这道题有点纠结,题倒不是很难,但是date命令的运用要够熟悉,这里我自己采取的做法是:

  1. 用户输入类似19960621格式的生日

  2. 将用户的生日转换为当年的(比如今年是2015):20159621

  3. 将当前日期和用户生日日期(已经转化为当年)都转换为用秒来表示

  4. 距离生日秒数=用户生日日期秒数-当前日期秒数

  5. 将“距离生日秒数”转换为天数

  6. 判断该天数的正负,从而得知用户的生日过了没有

脚本如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/bin/bash
# Program:
#       Telling you how many days are there before your birthday.
# History:
#        2015 / 07 / 26       XPleaf  First release
PATH=$PATH:~/bin
export PATH
 
read -p  "Please input your birthday like <19960621> : "  bith_input
 
bith_input_MD=$(echo $bith_input | awk  'BEGIN {FS=""} {print $5$6$7$8}' )
declare -i now_s=`date +%s`
declare -i bith_s=`date --date= "$(date +%Y)$bith_input_MD"  +%s`
declare -i total_s=$(($bith_s-$now_s))
declare -i total_day=$(($total_s/ 60 / 60 / 24 ))
if  "$total_day"  -gt  "0"  ];then
         echo  "There are $total_day day(s) before your bithday."
elif [  "$total_day"  -eq  "0"  ];then
         echo  "Today is your birthday!!!~Happy Birthday to you!"
else
         echo  "Your birthday in this year had gone!"
fi

执行结果:

1
2
3
[root@moban test]# sh sh02.sh 
Please input your birthday like < 19960621 > :  20150730
There are  3  day(s) before your bithday.

我感觉我这个方法是比较纠结的,所以我想肯定有很简单的方法的,知道的麻烦告诉我,非常感谢!


(3)让用户输入一个数字,程序可以由1+2+3...一直累加到用户输入的数字为止。

跟上题一样,也是交互式的,不过这题就简单多了,没有那么多的数据处理,而且在C语言中这样的题见过很多,所以是比较简单的一道题了,直接上脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/bin/bash
# Program:
#       You input the number, and I caculate  1 + 2 + 3 +...+the number.
# History:
#        2015 / 07 / 26
PATH=$PATH:~/bin
export PATH
 
echo  "You input the number, and I caculate 1+2+3+...+the number."
read -p  "Please input the number: "  nu
 
for ((i=s= 0 ;i<=$nu;i++))
do
         s=$(($s+$i))
done
 
echo  "1+2+3+...+$nu ==> $s"

执行结果:

1
2
3
4
[root@moban test]# sh sh03.sh 
You input the number, and I caculate  1 + 2 + 3 +...+the number.
Please input the number:  100
1 + 2 + 3 +...+ 100  ==>  5050

(4)编写一支程序,它的作用是先查看一下/root/test/logical这个名称是否存在,若不存在,则创建一个文件,使用touch来创建,创建完成后离开;如果存在的话,判断该名称是否为文件,若为文件则将之删除后新建一个目录,文件名为logical,之后离开;如果存在的话,而且该名称为目录,则删除此目录!

题目比较长,但逻辑是很简单的,简单梳理如下(这里假设/root/test目录是已经存在的):

  1. 判断/root/test目录下的logical这个名称是否存在

    (1)不存在    ==>使用touch来创建logical这个文件

    (2)存在

        a.logical是文件    ==>删除logical文件,同时创建logical目录

        b.logical是目录    ==>删除logical目录

显而易见的,用“&&”和“||”可以解决,但下面我为了表达式不写那么长,对于是否存在的判断我使用了if语句:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/bin/bash
# Program:
#       check the /root/test/logical
# History:
#        2015 / 07 / 26       XPleaf  First release
PATH=$PATH:~/bin
export PATH
 
echo  "check the /root/test/logical"
 
test -e /root/test/logical
i=$?
if  "$i"  -eq  "0"  ];then
         test -f /root/test/logical && rm -rf /root/test/logical && mkdir /root/test/logical || rm -rf /root/test/logical
else
         touch /root/test/logical
fi

执行结果:

情况一:/root/test/logical不存在

1
2
[root@moban test]# ls -l /root/test/logical
ls: 无法访问/root/test/logical: 没有那个文件或目录

执行一下脚本:

1
2
3
4
[root@moban test]# sh sh04.sh 
check the /root/test/logical
[root@moban test]# ls -l /root/test/logical
-rw-r--r--  1  root root  0  7 月   26  11 : 05  /root/test/logical

可以看到创建了logical这个文件。


情况二:/root/test/logical存在,且为文件(即上一步的执行结果)

1
2
3
4
[root@moban test]# sh sh04.sh              
check the /root/test/logical
[root@moban test]# ls -ld /root/test/logical
drwxr-xr-x  2  root root  4096  7 月   26  11 : 06  /root/test/logical

可以看到,此时的logical已经变成目录了,即logical文件被删除,同时创建了logical目录。


情况三:/root/test/logical存在,且为目录(即上一步的执行结果)

1
2
3
4
[root@moban test]# sh sh04.sh 
check the /root/test/logical
[root@moban test]# ls -l /root/test/logical
ls: 无法访问/root/test/logical: 没有那个文件或目录

可以看到,此时并没有/root/test/logical存在,即上一步创建的logical目录已经被删除了。


(4)我们知道/etc/passwd里面以:来分隔,第一列为账号名称。请写一个程序,可以将/etc/passwd的第一列取出,而且每一列都以一行字符串“The 1 account is "root""来显示,那个1表示行数。

直接用强大的awk就可以完成:

1
2
3
4
5
6
7
8
9
10
#!/bin/bash
# Program:
#       Remove the first list of the passwd and then output it
#       like "The count line one  is  : the content of the passwd.
# History:
#        2015 / 07 / 26       XPleaf  First release
PATH=$PATH:~/bain
export PATH
 
echo  "$(awk -F " : " '{print " The  " NR "  account  is  " $1}' /etc/passwd)"

执行结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
[root@moban test]# sh sh05.sh 
The  1  account  is  root
The  2  account  is  bin
The  3  account  is  daemon
The  4  account  is  adm
The  5  account  is  lp
The  6  account  is  sync
The  7  account  is  shutdown
The  8  account  is  halt
The  9  account  is  mail
The  10  account  is  uucp
The  11  account  is  operator
The  12  account  is  games
The  13  account  is  gopher
The  14  account  is  ftp
The  15  account  is  nobody
The  16  account  is  dbus
The  17  account  is  vcsa
The  18  account  is  abrt
The  19  account  is  haldaemon
The  20  account  is  ntp
The  21  account  is  saslauth
The  22  account  is  postfix
The  23  account  is  sshd
The  24  account  is  tcpdump
The  25  account  is  oldboy
The  26  account  is  test
The  27  account  is  apache
The  28  account  is  www
The  29  account  is  mysql

这道题有点坑,如果知道这道题是考awk的或者本身对awk非常熟悉的,一下子就可以想得到,但是如果前面说的两个条件都没有,那就麻烦了!刚开始我没有想到是用awk,就用了非常苦逼的方法:要出行号,就得用循环,从1开始加起;要用循环,就得知道循环结束的条件,即要知道/etc/passwd的行数;要知道行数,就得用wc······然后用cut来取第一列,再用sed来输出每一行(也是用循环)。

可惜最后瞎折腾了,理论上确实是可以实现的,我在Linux命令行上就搞了出来,但是在用vim编辑时,下面的这一行就有问题了,即sed的语法上面:

1
user=$(sed -n  '$ip'  /etc/passwd | cut -d ':'  -f  1 )

'$ip'这里,其实我是想控制输出第几行,i是个循环的变量,但是这里却无法识别,所以最后就做不了了,还好有强大的awk,不然那就坑了啊!两种方法,那差太远了啊!

关于这个语法上面的,我也想知道为什么不行啊,知道的麻烦告诉一声了,非常感谢啊!




本文转自 xpleaf 51CTO博客,原文链接:http://blog.51cto.com/xpleaf/1678565,如需转载请自行联系原作者

相关文章
|
算法 安全 JavaScript
通过Postman实现API网关的请求签名与调试
Postman是一个非常强大的HTTP发包测试工具, 目前Postman已经提供了Windows/Mac/Linux系统的客户端的下载,使用很方便。不过API网关的调试,需要对HTTP请求进行签名才能调用,无法使用简单的curl等发包工具完成,但我们可以使用Postman工具提供的Pre-request Script脚本来实现API网关的签名功能,实现API的调试功能。
6713 0
|
存储 Java
Java编程中的对象和类
在Java的世界中,“对象”与“类”是构建一切的基础。就像乐高积木一样,类定义了形状和结构,而对象则是根据这些设计拼装出来的具体作品。本篇文章【8月更文挑战第31天】 将通过一个简单的例子,展示如何从零开始创建一个类,并利用它来制作我们的第一个Java对象。准备好让你的编程之旅起飞了吗?让我们一起来探索这个神奇的过程!
|
Java
SpringBoot 映射路径中 匹配正则表达式
SpringBoot 映射路径中 匹配正则表达式
422 0
|
存储 缓存 Java
适合各大资源网投稿html源码
适合各大资源网投稿html源码,源码由HTML+CSS+JS组成,记事本打开源码文件可以进行内容文字之类的修改,双击html文件可以本地运行效果,也可以上传到服务器里面,重定向这个界面
351 1
适合各大资源网投稿html源码
|
消息中间件 SpringCloudAlibaba Java
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(八)Config服务配置+bus消息总线+stream消息驱动+Sleuth链路追踪
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(八)Config服务配置+bus消息总线+stream消息驱动+Sleuth链路追踪
1668 0
|
消息中间件 Java 数据安全/隐私保护
07Window下ActiveMQ的下载与安装
07Window下ActiveMQ的下载与安装
236 0
|
安全 数据安全/隐私保护
VulnHub-hackNos:Os-hackNos-2.1-WP
VulnHub-hackNos:Os-hackNos-2.1-WP
218 0
VulnHub-hackNos:Os-hackNos-2.1-WP
|
Android开发 C语言
【Android 逆向】Android 进程注入工具开发 ( 远程进程 注入动态库 文件操作 | Android 进程读取文件所需的权限 | fopen 打开文件标志位 | 验证文件权限 )
【Android 逆向】Android 进程注入工具开发 ( 远程进程 注入动态库 文件操作 | Android 进程读取文件所需的权限 | fopen 打开文件标志位 | 验证文件权限 )
544 0
【Android 逆向】Android 进程注入工具开发 ( 远程进程 注入动态库 文件操作 | Android 进程读取文件所需的权限 | fopen 打开文件标志位 | 验证文件权限 )
|
JavaScript 前端开发
学习JavaScript笔记
学习JavaScript笔记
106 0