shell练习

shell常见面试题

什么是解释性语言?什么是编译型语言?

解释性语言:程序不需要编译,程序在运行时由解释器翻译成机器语言,每执行一次都要翻译一次。因此效率比较低。
比如Python/javaScript/Shell等都是解释型语言。
编译型语言:程序在执行之前需要个专门的编译过程,把程序编译成为机器语言文件,运行时不需要重新翻译,直接使用编译的结果就行了

程序执行效率高,依养编译器,跨平台性差些。如C、C++、java

写一个脚本输入任意数组或则数字例如 2 3 4 5 6 7 8 9,输出最大值、最小值、平均值
#!/bin/bash

#DESC:求数组的最大最小以及平均值
#AUTHOR:王壮壮
#...

max=$1
min=$1
sum=0

for i in "$@"
do
	if [ $max -lt $i ]
	then
		max=$i
	fi
	if [ $min -gt $i ]
	then
		min=$i
	fi
	sum=$[$sum+$i]
done
echo "max:$max"
echo "min:$min"
avg=$(echo "scale=2;$sum/$#"|bc)
avg1=`echo "scale=2;$sum/$#" | bc`
echo "avg:$avg"
echo "avg1:$avg1"

输出

sh day05_1.sh  1 2 3 4 5 6
max:6
min:1
avg:3.50
avg1:3.50
写一个脚本输入任意数组或则数字例如 2 4 3 5 9 7 8 6,按照从小到大排序后输出
vim day05_2.sh

#!/bin/bash

#DESC:写一个脚本输入任意数组或则数字例如 2 4 3 5 9 7 8 6,按照从小到大排序后输出
#AUTHOR:王壮壮
#...

arr=(2 4 3 5 9 7 8 6)
temp=0;
for ((i=0;i<${#arr[*]}-1;i++))
do
        for ((j=0;j<${#arr[*]}-1-i;j++))
        do
                if [ ${arr[j]} -gt ${arr[j+1]} ]
                then
                        temp=${arr[j]}
                        arr[j]=${arr[j+1]}
                        arr[j+1]=$temp
                fi
        done
done
echo ${arr[*]}
--------------------------------------------------
vim day05_02.sh
#!/bin/bash
arr=($@)

for ((i=1;i<${#arr[@]};i++))
do
        for ((j=$[i+1];j<${#arr[@]};j++))
        do
                tmpvalue=${arr[$i]}
                if [ ${arr[$j]} -lt $tmpvalue ]
                then
                arr[$i]=${arr[$j]}
                arr[$j]=$tmpvalue
                fi
        done
done
echo ${arr[@]}

输出

[root@Linux01 shell]# sh day05_2.sh
2 3 4 5 6 7 8 9
[root@Linux01 shell]# 
---------------------------------------------
[root@Linux01 shell]# sh day05_02.sh  1 3 5 4 2 6
1 2 3 4 5 6
[root@Linux01 shell]# 
完成/root/shell_test/文件夹下完成一个脚本
1.判断aaa.txt文件是否存在,存在则往文件中写入bbb,如果不存在,创建aaa.txt文件,往文件中写入bbb
#!/bin/bash
if [ -e aaa.txt ]
then
	echo bbb >> aaa.txt
else
	touch aaa.txt
	echo bbb >> aaa.txt
fi
2.每一分钟执行一次脚本
* * * * * /bin/bash 脚本的绝对路径
判断/root/class26/inittab.txt文件是否大于100行,如果大于,则显示”inittab is a big
#!/bin/bash

# 获取该文件的行数
num=$(awk 'BEGIN{sum=0}{sum+=1}END{print sum}' inittab.txt)
# num=$(awk -v sum=0'{sum+=1}END{print sum}' inittab.txt)
# num=$(cat inittab.txt | wc -l)

if [ $num -gt 100 ]
then
        echo "inittab is a big file"
else
        echo "inittab is a small file"
fi
写出一个脚本程序,给定一个文件,比如:/root/class26/inittab.txt
a、判断这个文件中是否有空白行? 
b、如果有,则显示其空白行的总行数,否则显示没有空白行
#!/bin/bash
num=$(awk "/^$/{print NR}" inittab.txt | wc -l)
# num=$(awk -v sum=0 "/NR/{sum=sum+1}END(print sum)" inittab.txt)
# num=`grep "^$" inittab.txt | wc -l`
if [ $num -gt 0 ]
then
        echo "文件中存在空白行,共有"$num"行"
else
        echo "文件没有空白行"
fi

输出

[root@Linux01 shell]# sh day05_05.sh 
文件中存在空白行,共有8行
给定一个文件,如果是普通文件,就显示出来,如果是目录文件,也显示出来,否则就显示“无法识别”
#!/bin/bash
filename=$1
if [ -f $filename ]
then
		echo $filename "存在并且是一个文件"
elif [ -d $filename ]
then
		echo $filename "存在并且是一个文件夹"
		cd $filename
		ls -l
else
		echo $filename "无法识别"
fi
写一个脚本,给脚本传递3个参数 两个数字,一个运算符,根据运算符计算出结果
#!/bin/bash
case $3 in
        "+")
        echo $[$1+$2]
        ;;
        "-")
        echo $[$1-$2]
        ;;
        "\*")
        echo $[$1*$2]
        ;;
        "/")
        if [ $2 -eq 0 ]
        then
                echo "0不能当除数"
        else
                echo $[$1+$2]
        fi
        ;;
        *)
        echo "无法识别计算"
        ;;
esac

测试

[root@Linux01 shell]# sh day05_07.sh 2 8 \\*
16
[root@Linux01 shell]# 
8.使用脚本完成批量创建用户创建(100个用户例如 ljh1~ljh100 )今天完成
#!/bin/bash
#/root/calss_shell/name.txt 里面存放用户名
USERS=$(cat name.txt)
echo $USERS
for UNAME in $USERS
do
		echo $UNAME
		useradd $UNAME
		echo "123456" | passwd --stdin $NAME
done

测试

错误示范

[root@Linux01 shell]# bash day05_08.sh
张三 李四 王五 马六 赵七
张三
useradd:无效的用户名“张三”
passwd: 未知的用户名称 '张三'。
李四
useradd:无效的用户名“李四”
passwd: 未知的用户名称 '李四'。
王五
useradd:无效的用户名“王五”
passwd: 未知的用户名称 '王五'。
马六
useradd:无效的用户名“马六”
passwd: 未知的用户名称 '马六'。
赵七
useradd:无效的用户名“赵七”
passwd: 未知的用户名称 '赵七'[root@Linux01 shell]# cat name.txt 

正确示范

[root@Linux01 shell]# bash day05_08.sh
zhangsan lisi wangwu maliu zhaoqi
zhangsan
useradd:用户“zhangsan”已存在
更改用户 zhangsan 的密码 。
passwd: 所有的身份验证令牌已经成功更新。
lisi
更改用户 lisi 的密码 。
passwd: 所有的身份验证令牌已经成功更新。
wangwu
更改用户 wangwu 的密码 。
passwd: 所有的身份验证令牌已经成功更新。
maliu
更改用户 maliu 的密码 。
passwd: 所有的身份验证令牌已经成功更新。
zhaoqi
更改用户 zhaoqi 的密码 。
passwd: 所有的身份验证令牌已经成功更新。

用户名不能为中文,犯了最基础的错误

创建脚本检查软件包是否安装
#!/bin/bash

appName=$1
tmp=`rpm -qa $appName`
echo $tmp
if [ $tmp ]
then
        echo "$appName 软件已安装"
else
        echo "$appName 软件未安装"
fi

测试

[root@Linux01 shell]# sh day05_09.sh firefox
firefox-52.8.0-1.el6.centos.x86_64
firefox 软件已安装
编写脚本打印99乘法表
#!/bin/bash
num=$1
row=1
while [ $row -le $num ]
do
        col=1
        while [ $col -le $row ]
        do
                printf "$row*$col=$[$row*$col]\t"
                col=$[col+1]
        done
        echo
        row=$[row+1]
done

测试

[root@Linux01 shell]# sh day05_10.sh 9
1*1=1	
2*1=2	2*2=4	
3*1=3	3*2=6	3*3=9	
4*1=4	4*2=8	4*3=12	4*4=16	
5*1=5	5*2=10	5*3=15	5*4=20	5*5=25	
6*1=6	6*2=12	6*3=18	6*4=24	6*5=30	6*6=36	
7*1=7	7*2=14	7*3=21	7*4=28	7*5=35	7*6=42	7*7=49	
8*1=8	8*2=16	8*3=24	8*4=32	8*5=40	8*6=48	8*7=56	8*8=64	
9*1=9	9*2=18	9*3=27	9*4=36	9*5=45	9*6=54	9*7=63	9*8=72	9*9=81	
编写函数实现取出ip地址
function getip()
{
		ip=`ifconfig | grep "Bcast" | awk -F : '{print $2}' | awk -F " " '{print $2}'`
		echo $ip
}

1) 如何向脚本传递参数,举例说明 ?
#!/bin/bash

# $1:获取传入的第一个参数
# ${10}:获取传入的第一个参数
# $0:获取脚本名
echo $1 ${10} $0
[root@Linux01 shell]# vim show.sh
[root@Linux01 shell]# chmod a+x show.sh 
[root@Linux01 shell]# ./show.sh 1 2 3 4 6 hello world java python 10 17
1 10 ./show.sh
[root@Linux01 shell]# chmod a+x show.sh 
2) 如何在脚本中使用参数 ?
第一个参数 : $1,第二个参数 : $2
需求:脚本会复制文件(arg1) 到目标地址(arg2)

#!/bin/bash

cp $1 $2

测试

./copy.sh file1.txt /tmp/
3) Shell中的特殊变量有哪些分别表示什么含义?自定义变量时,变量的作用域范围有哪些分类?
$n 获取输入脚本的参数 
$# 获取输入参数的个数
$* 获取输入脚本的所有参数,会把所有参数看成一个整体
$@ 获取输入脚本的所有参数,会把每个参数看成一个个体
$? 获取上次命令的执行结果,如果成功则输出0;反之非0
自定义用户变量:只针对当前用户和当前会话有效
自定义全局环境变量:针对当前会话下的所有用户有效--->export a=111
自定义系统环境变量:针对所有会话所有用户都有效--->/etc/profile --> echo "export NAME=111" --> 生效:source /etc/profile
4) 如何获取文件的最后一行 ?
[root@Linux01 ~]# cat a.txt 
linux常用命令


ls
cd
mkdir
rmdir
touch
rename
-- 获取文件最后一行
[root@Linux01 ~]# tail -1 a.txt 
rename
-- 获取文件第一行
[root@Linux01 ~]# head -1 a.txt 
linux常用命令
[root@Linux01 ~]#
5) 如何获取文件的第一行 ?

参考上图

6) 如何获取一个文件每一行的第三个元素 ?
cut -b 3
cut -c 3
7) 如何查看脚本语法错误,如何查看脚本的执行流程
bash -n 脚本名称
bash -x 脚本名称
8) 举例如何写一个函数 ?
function example()
{echo "Hello World"return 0
}
9) 如何连接两个字符串变量?
V1="Hello"
V2="World"
V3=${V1}${V2}
echo $V3
10) 如何进行两个整数相加,能想出几种,写几种 ?
a=1
b=2
echo $(($a+$b))
echo $((a+b))
echo $[$a+$b]
echo $[a+b]
expr $b + $b #'+'前后要留下空格
11) 如何检查文件系统中是否存在某个文件 ?
if [ -e 文件路径 ]
then 
		echo "File exists"
fi
12) 写出 shell 脚本中的循环语法 ?
for ((i=0;i<100;i++))
do 
done
----------------
for i in "a b c d"
do
done
----------------
while [ 条件表达式 ]
do
done
----------------
until [ 条件表达式 ]
do
done
13) 每个脚本开始的 #!/bin/sh 或 #!/bin/bash 表示什么意思 ?
表示脚本使用的解析器类型 sh -> /bin/bash

执行脚本
sh show.sh
bash show.sh
source show.sh
./show.sh #给脚本添加执行权限
14) 如何获取文本文件的第 10 行内容 ?
head -10 | tail -1
15) 命令:[ -z “” ] && echo 0 || echo 1 的输出是什么? (今天完成)
[root@Linux01 shell]#  [ -z "" ] && echo 0 || echo 1
0
[root@Linux01 shell]# 
16) “export” 关键字有什么用 ?
创建变量的时候可用,可以改变变量的作用域
17) “chmod 500 script” 做什么 ?

修改文件权限为 r-x — ---

18) “>” 符号做什么用的?
> 重定向输出流到一个文件或者另一个流
$> 重定向异常信息输出流到文件
19) & 和 && 有什么区别
&&:当前一个脚本成功完成执行才执行后面的命令,在脚本的时候使用
&:同时运行多个命令和脚本
20) 命令: name=John && echo ‘My name is $name’ 的输出是什么
[root@Linux01 shell]# name=John && echo 'My name is $name'
My name is $name
[root@Linux01 shell]# name=John && echo "My name is $name"
My name is John
21) bash shell 脚本中哪个符号用于注释(多行注释和单行注释) ?
:<<EOF
	这是多行注释
EOF

# 这是单行注释
22) 如何只用 echo 命令获取字符串变量的一部分 ?
echo ${variable:x:y}
x - 起始位置
y - 截取长度
23) 如果给定字符串 variable=“User:123:321:/home/dir”,获取用户的家目录
[root@Linux01 shell]# variable="User:123:321:/home/dir"
[root@Linux01 shell]# echo $variable
User:123:321:/home/dir
[root@Linux01 shell]# echo $variable | awk -F : '{print $4}'
/home/dir
[root@Linux01 shell]# 
24) 如何使用 awk 列出 UID 小于 100 的用户?
awk -F : '{if($3<100){print ""$1","$3"}}' /etc/passwd
26) 如何计算本地用户数目(统计/etc/passwd中的用户数)?
awk -v sum=0 '{sum+=1}END{print sum}' /etc/passwd
27) 如何将整数 a 加到 b 并赋值给 c ?
c=$[a+b]
c=`echo $((a+b))`
28) 如何去除文本中的所有空格?
echo $string | sed -e 's/ //g'
echo $string | tr -d " "
29) 写出输出数字 0 到 100 中 3 的倍数(0 3 6 9 …)的命令?
#!/bin/bush

for ((i=1;i<101;i++))
do
        if [ $[i%3] -eq 0 ]
        then
                echo $i
        fi
done
30) 如何传递给脚本的所有参数?
echo $*echo $@
31) [ $a == $b ] 和 [ $a -eq $b ] 有什么区别
 [ $a == $b ][ $a -eq $b ] 有什么区别?
 [ $a == $b ] -用于字符串比较
 [ $a -eq $b ] -用于数字比较
32) 写出测试 $a 是否大于 12 的命令 ?
[ $a -gt 12 ]
33) 如何列出以 ab 或 xy 开头的用户名 ?
awk -F : '/^ab|^xy{print $1}' /etc/passwd
35) 如何在 bash 中定义数组 ? 如何打印数组的第一个元素 ? 如何打印数组的所有元素 ? 如何输出所有数组索引 ? 如何移除数组中索引为 2 的元素 ?
-- 定义数组
[root@Linux01 shell]# array=(1 2 3 "hello word" java)
-- 打印数组中的第一个元素
[root@Linux01 shell]# echo ${array[0]}
1
-- 打印数组的所有元素 第一种
[root@Linux01 shell]# echo ${array[@]}
1 2 3 hello word java
-- 打印数组的所有元素 第二种
[root@Linux01 shell]# echo ${array[*]}
1 2 3 hello word java
-- 获取数组长度
[root@Linux01 shell]# echo ${#array[*]}
5
-- 输出所有数组索引
[root@Linux01 shell]# echo ${!array[@]}
0 1 2 3 4
-- 移除数组中索引为 2 的元素
[root@Linux01 shell]# unset array[2]
[root@Linux01 shell]# echo ${!array[@]}
0 1 3 4
-- 移除数组
[root@Linux01 shell]# unset array
[root@Linux01 shell]# echo ${!array[@]}

[root@Linux01 shell]#
37) shell解析器有哪些?Centos6和7默认使用的是哪一个
bin/bash -- 默认使用
bin/sh
bin/sch
bin/tcsh
bin/nologin
38)累加
[root@Linux01 shell]# mkdir ketanganli
[root@Linux01 shell]# cd ketanganli/
[root@Linux01 ketanganli]# vim for01.sh

#!/bin/bash
#DESC:使用for循环完成1-100的累加
sum=0
for ((i=0;i<101;i++))
do
        sum=$[sum+i]
done
echo "1-100的累加和为$sum"

[root@Linux01 ketanganli]# bash for01.sh 
1-100的累加和为5050
--------------------------------------------------------------
[root@Linux01 ketanganli]# cp for01.sh  for02.sh 
[root@Linux01 ketanganli]# vim for02.sh 

#!/bin/bash
#DESC:使用for循环完成1-100的偶数累加
sum=0
for ((i=0;i<101;i++))
do
        if [ $[i%2] -eq 0 ]
        then
                sum=$[sum+i]
        fi
done
echo "1-100的偶数累加和为$sum"
[root@Linux01 ketanganli]# bash for02.sh 
1-100的偶数累加和为2550

39) 遍历数组
[root@Linux01 ketanganli]# vim for03.sh

#!/bin/bash
#DESC:使用for in 循环遍历数组
#...
arr=(2,1,3,4,7,5,80)
for i in ${arr[*]}
do
        echo $i
done

[root@Linux01 ketanganli]# bash for03.sh 
2,1,3,4,7,5,80
40) 区分$ 后面跟*和跟@的区别
[root@Linux01 ketanganli]# vim for04.sh

#!/bin/bash

#DESC:使用for循环对比 $* 和 $@

for i in $*
do
        echo "\$*:" $i
done
echo "--------" 
for i in $@
do
        echo "\$@:" $i
done

# 输出
[root@Linux01 ketanganli]# bash for04.sh 1 3 5 6 8 9
$*: 1
$*: 3
$*: 5
$*: 6
$*: 8
$*: 9
--------
$@: 1
$@: 3
$@: 5
$@: 6
$@: 8
$@: 9
[root@Linux01 ketanganli]#

上图可以看出,两者并没有什么区别,但是请看下图

#!/bin/bash

#DESC:使用for循环对比 $* 和 $@
#给$*和$@加上引号
for i in "$*"
do
        echo "\$*:" $i
done
echo "--------" 
for i in "$@"
do
        echo "\$@:" $i
done

# 输出
[root@Linux01 ketanganli]# bash for04.sh 1 3 5 6 8 9
$*: 1 3 5 6 8 9
--------
$@: 1
$@: 3
$@: 5
$@: 6
$@: 8
$@: 9

由此得出

	$* 把所有的参数看成一个整体
	$@ 把所有的参数区别对待,每个参数都是一个个体
sort排序
[root@Linux01 ketanganli]# vim chengji.txt
[root@Linux01 ketanganli]# sort -t ":" -k 2 chengji.txt 
zhangsan:100:5.4
maliu:60:5.0
zhaoqi:70:1.6
lisi:80:4.2
wangwu:90:2.3
[root@Linux01 ketanganli]# sort -t ":" -nk 2 chengji.txt 
maliu:60:5.0
zhaoqi:70:1.6
lisi:80:4.2
wangwu:90:2.3
zhangsan:100:5.4
[root@Linux01 ketanganli]# sort -t ":" -nrk 2 chengji.txt 
zhangsan:100:5.4
wangwu:90:2.3
lisi:80:4.2
zhaoqi:70:1.6
maliu:60:5.0
[root@Linux01 ketanganli]# 
[root@Linux01 ketanganli]# sort -t ":" -nrk 2 chengji.txt | head -n 2
zhangsan:100:5.4
wangwu:90:2.3
[root@Linux01 ketanganli]# sort -t ":" -nrk 2 chengji.txt | head -n 2 | cut -d ":" -f 1
zhangsan
wangwu

截取ip地址
[root@Linux01 shell]# ifconfig
eth0      Link encap:Ethernet  HWaddr 00:0C:29:C5:2D:09  
          inet addr:192.168.150.100  Bcast:192.168.150.255  Mask:255.255.255.0
          inet6 addr: fe80::20c:29ff:fec5:2d09/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:11856 errors:0 dropped:0 overruns:0 frame:0
          TX packets:7090 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:971347 (948.5 KiB)  TX bytes:2269231 (2.1 MiB)
          Interrupt:19 Base address:0x2000 

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:4 errors:0 dropped:0 overruns:0 frame:0
          TX packets:4 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:240 (240.0 b)  TX bytes:240 (240.0 b)
----------------------------------------------------------------------------------
# 截取上面的ip地址
[root@Linux01 shell]# ifconfig | grep Bcast | cut -d ":" -f 2 | cut -d " " -f 1
192.168.150.100

awk
功能描述:是一门编程语言,也是一个强大的文本分析工具,逐行扫描文件,默认从第一行到最后一行,寻找匹配特定模式的行,并在这些行上进行你想要的操作。

语法: awk 选项 'pattern1{action1} pattern2{action2}...' 文件名
 pattern:表示AWK在数据中查找的内容,就是匹配模式
 action:在找到匹配内容时所执行的一系列命令

选项		功能
 -F		指定输入文件的分隔符
 -v		赋值一个用户定义变量

案例

(1)搜索passwd文件以root关键字开头的所有行,并输出该行的第7列。
# 先查看root开头的行有哪些
[root@Linux01 shell]# cat passwd | grep '^root'
root:x:0:0:root:/root:/bin/bash

https://www.cnblogs.com/pal857/p/12502573.html

你可能感兴趣的:(linux)