shell入门保姆教程

本文详细介绍了Shell脚本的基础知识,包括Shell的用途、基本元素、命令如echo、eval、exec、read和shift的使用。还讨论了$#、$n、$?等特殊变量以及&*与&@的区别。此外,文章展示了如何设置脚本的版权注释、定义环境变量、执行脚本的不同方式以及Vim编辑器中设置缩进的方法。最后,提到了引用在Shell中的作用,如转义字符、单引号和双引号的使用。
摘要由CSDN通过智能技术生成

1. shell基本知识

shell(计算机外壳),它是命令解释器,在操作系统的最外层,把用户的输入解释给操作系统。
如果有一系列经常需要使用的命令,把它存储在一个文件里,shell可以读取这个文件并顺序执行其中的命令,我们把这样的文件就叫shell脚本。shell脚本按行解释文件里的命令。

shell脚本的基本元素

对于一个基本的Shell程序来说,应该拥有以下基本元素:

[root@localhost ~]# cat /etc/shells
/bin/sh
/bin/bash
/sbin/nologin
/usr/bin/sh
/usr/bin/bash
/usr/sbin/nologin
[root@localhost ~]# echo $SHELL
/bin/bash
  1. 声明:声明用哪个命令解释器来解释并执行当前脚本文件中的语句,一般写的解释器为
#!/bin/bash 
  1. 命令:可执行语句,实现程序的功能。
  2. 注释:说明某些代码的功能,通过在代码中增加注释可以提高程序的可读性。
    (1)单行注释:#开头的一整行都是注释,例如:
#comment1
#comment2
#comment3
……

(2)多行注释,使用冒号“:”配合here document可实现多行注释,例如:

:<<BLOCK
……注释内容
BLOCK
  1. 赋予rx的权限

2.命令使用

echo

作用:可在屏幕上输出信息

echo参数选项说明
-n不换行输出
-e解析转义字符
转义字符说明
\n换行
\r回车
\t制表符
\b退格
\v纵向制表符

示例:

#不加任何参数时的输出
[jzl@localhost ~]$ echo i am a student
i am a student
[jzl@localhost ~]$ 
# 加上-n参数后
[jzl@localhost ~]$ echo -n i am a student
i am a student[jzl@localhost ~]$ 
#加入转义字符\t后,不写入参数
[jzl@localhost ~]$ echo i\tam\ta\tstudent\t
itamtatstudentt
#直接加上参数-e
[jzl@localhost ~]$ echo -e i\tam\ta\tstudent\t
itamtatstudentt
#将后面输入的用双引号
[jzl@localhost ~]$ echo -e "i\tam\ta\tstudent\t"
i	am	a	student
#使用转义字符\n
[jzl@localhost ~]$ echo -e "i am a student\n"
i am a student

[jzl@localhost ~]$ 

eval

功能:当shell程序执行到eval语句时,shell读入参数args,并将它们组合成一个新的命令,然后执行。
命令格式:eval args
示例:

[jzl@localhost ~]$ a='shuju;head -2 /etc/passwd'
[jzl@localhost ~]$ echo $a
shuju;head -2 /etc/passwd
[jzl@localhost ~]$ eval echo $a
shuju
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
#试一下管道,发现eval不适合标准输入
[jzl@localhost ~]$ echo $a|eval
[jzl@localhost ~]$
#依次试一试发现一下eval是如何执行的
[jzl@localhost ~]$ eval echo 'shuju'
shuju
[jzl@localhost ~]$ eval echo 'head -2 /etc/passwd'
head -2 /etc/passwd
[jzl@localhost ~]$ head -2 /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
[jzl@localhost ~]$ eval echo "shuju;head -2 /etc/passwd"
shuju
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
[jzl@localhost ~]$ eval echo "shuju";head -2 /etc/passwd
shuju
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin

exec

作用:能够在不创建新的子进程的前提下,转去执行指定的命令,当指定的命令执行完毕后,该进程就终止了。
示例:

[jzl@localhost ~]$ cd /etc/
[jzl@localhost etc]$ exec cd /home
Connection to 192.168.10.128 closed.

read

作用:可从标准输入读取字符串等信息,传给shell程序内部定义的变量

read参数选项说明
-pprompt:设置提示信息
-ttimeout :设置等待时间,单位默认为秒

示例:

#读取字符串,其提示为请输入姓名:,等待时间为5s,执行后不输入姓名等待5s,会自动结束
[root@localhost ~]# read -p "please input name:" -t 5 name1
please input name:[root@localhost ~]#
[root@localhost ~]# read -p "please input name:" name1 name2
please input name:Tom Johy
[root@localhost ~]# echo $name1
Tom
[root@localhost ~]# echo $name2
Johy
#使用read从标准输入读取两个变量: name1和name2, 要求name1包含空格
[root@localhost ~]# read -p "please input name:" name1 name2
please input name:James\ Webb Tom
[root@localhost ~]# echo $name1
James Webb
[root@localhost ~]# echo $name2
Tom
[root@localhost ~]#

shift

作用:shift,在程序中每使用一次shift语句,都会使所有的位置参数依次向左移动一个位置,并使位置参数$#减1,直到减到0为止。

$# $* $@ $n $?的使用

变量说明
$#命令行参数的个数
$n表示传递给脚本的第n个参数,例如$1表示第一个参数,$2表示第二个参数,$3表示第三个参数
$0当前脚本的名称
$*以"参数1 参数2 参数3…"的形式返回所有参数的值
$@以“参数1”“参数2”“参数3”…的形式返回所有的值
$?前一个命令或者函数的返回状态码。" $ ?" 的返回值用法:(1)判断命令、脚本或函数等程序是否执行成功(2)若在脚本中调用执行“exit 数字”,则会返回这个数字给 “$ ?” 变量(3)如果是在函数里,则通过“return 数字”把这个数字以函数值的形式传给“$?”
$$返回本程序的进程ID(PID),不常用
$!获取上一个在后台工作的进程的进程号,不常用
$_保存之前执行的命令的最后一个参数,不常用
示例:
[root@localhost day1]# vim shift_test.sh 
# 命令行参数的个数
echo "count1: $#"
# 第1个位置参数
echo "data1: $1"
# 第2个位置参数
echo "data2: $2"
# 当前脚本的名称
echo "name: $0"
# 所有参数
echo "all_data1: $*"
echo "all_data2: $@"
# 当前进程的PID
echo "PID: $$"
shift
#shift过后再次查看命令行参数的个数
echo "count2: $#"
[root@localhost day1]# bash shift_test.sh 1234 5678
count1: 2
data1: 1234
data2: 5678
name: shift_test.sh
all_data1: 1234 5678
all_data2: 1234 5678
PID: 9459
count2: 1

&*与&@的区别

会发现&和&@表面显示是一样,不同的在哪呢?
$
:以"参数1 参数2 参数3…"的形式返回所有参数的值
例:“1234 5678”
$@:以“参数1”“参数2”“参数3”…的形式返回所有的值
示例1: “1234”“5678”

[root@localhost day1]# set -- "i have" a cat
[root@localhost day1]# echo $#
3
[root@localhost day1]# echo $*
i have a cat
[root@localhost day1]# echo $@
i have a cat
[root@localhost day1]#  for i in $*;do echo $i;done
i
have
a
cat
[root@localhost day1]#  for i in $@;do echo $i; done
i
have
a
cat
[root@localhost day1]# for i in "$*";do echo $i;done
i have a cat
[root@localhost day1]# for i in "$@";do echo $i;done
i have
a
cat

示例2:

[root@localhost day1]# cat shift_test2.sh 
for i in "$*"
do
    echo $i
done
echo "--------------"
for i in "$@"
do
    echo $i
done
echo "--------------"
[root@localhost day1]# bash shift_test2.sh 1234 5678
1234 5678
--------------
1234
5678
--------------
[root@localhost day1]# 

exit(要求退出码为222)

作用:退出shell程序。在exit之后可以有选择地指定一个数作为返回状态

[root@localhost day1]# vim exit_test.sh
echo "123"
exit 222
echo "456"
[root@localhost day1]# bash exit_test.sh 
123
[root@localhost day1]# echo $?      #查看退出码
222

如何快速如何快速生成脚本开头的版本版权注释信息

[root@localhost ~]# vim ~/.vimrc
autocmd BufNewFile *.py,*.cc,*.sh,*.java exec ":call SetTitle()"
func SetTitle()
if expand("%:e") == 'sh'
call setline(1,"#!/bin/bash")
call setline(2,"#########################")
call setline(3,"#File name:".expand("%"))
call setline(4,"#Version:v1.0")
call setline(5,"#Email:admin@test.com")
call setline(6,"#Created time:".strftime("%F %T"))
call setline(7,"#Description:")
call setline(8,"#########################")
call setline(9,"")
endif
endfunc
# 然后再创建.sh的文件,发现会自动生成注释信息
[root@localhost ~]# vim haha.sh
#!/bin/bash
#########################
#File name:haha.sh
#Version:v1.0
#Email:admin@test.com
#Created time:2022-08-15 19:36:51
#Description:
#########################

3.定义自定义环境变量

export

作用:设置或显示环境变量
示例:

#显示所有环境变量
[root@localhost day1]# export
declare -x DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/0/bus"
declare -x DISPLAY="localhost:10.0"
.......
declare -x which_declare="declare -f"
#设置环境变量
[root@localhost day1]# a=1234
[root@localhost day1]# export a   #设置a为环境变量
[root@localhost day1]# echo $a
1234
[root@localhost day1]# unset a
[root@localhost day1]# echo $a

[root@localhost day1]# 

declare

作用:使用declare声明变量类型:既然所有变量的默认类型是字符串型,那么只要我们把变 量声明为整数型就可以进行运算了。使用declare命令就可以实现声明变量的类型。
declare [+/-][选项] 变量名

变量说明
选项说明
-给变量舍得类型属性
+取消变量的类型属性
-a将变量声明为数组型
-i将变量声明为整型
-x将变量声明为环境变量
-r将变量声明为只读变量
-p查看变量的被声明的类型
针对root用户的所有连接root_data=root
针对所有用户的变量all_data=all
查看所有的环境变量查看所有变量

示例:

#设置环境变量 
[root@localhost day1]# declare -x test=1234  #用declare命令-x选项将test=123声明为环境变量。
[root@localhost day1]# env | grep test  # #在env中查找是否有test的环境变量
OLDPWD=/root/test
test=1234
PWD=/root/test/day1
#查看所有环境变量
[root@localhost day1]# declare 
......
#查看所有环境变量
[root@localhost day1]# env
......

示例:
针对root用户的所有连接:root_data=root
针对所有用户的变量: all_data=all

[root@localhost day1]# root_data=root
[root@localhost day1]# export root_data
[root@localhost day1]# all_data=all
[root@localhost day1]# declare -x all_data
[root@localhost day1]# env | grep data
all_data=all
root_data=root
[root@localhost day1]# 
#查看所有环境变量
[root@localhost day1]# declare 
......
#查看所有环境变量
[root@localhost day1]# env
......
#显示所有环境变量
[root@localhost day1]# export
declare -x DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/0/bus"
declare -x DISPLAY="localhost:10.0"
.......
declare -x which_declare="declare -f"

4.脚本执行的方式及特点

1)交互式

[root@localhost day1]# for filename in `ls /etc`
> do
> if echo "$filename" | grep "passwd"
> then
> echo "$filename"
> fi
> done
passwd
passwd
passwd-
passwd-
[root@localhost ~]# 

(2)作为程序文件执行(常用)

[root@localhost day1]# vim method2.sh
#!/bin/bash
for filename in `ls /etc`
do
if echo "$filename" | grep "passwd"
then
echo "$filename"
fi
done
[root@localhost day1]# bash method2.sh 
passwd
passwd
passwd-
passwd-

5.执行脚本的方法

(1)bash ./filename.sh(产生子进程,再运行,使用当前指定的bash shell去运行)

[root@localhost day1]# bash method.sh 
hello

(2)./filename.sh(产生子进程,再运行,使用脚本里面指定的shell去运行。使用该种方式执行需要x权限)

[root@localhost day1]# ./method.sh
-bash: ./method.sh: Permission denied
[root@localhost day1]# chmod a+rx method.sh 
[root@localhost day1]# ./method.sh
hello

(3)source ./filename.sh(source命令是一个shell内部命令,其功能是读取指定的shell程序文件,并且依次执行其中的所有的语句,并没有创建新的子shell进程,所以脚本里面所有创建的变量都会保存到当前的shell里面)

[root@localhost day1]# source ./method.sh 
hello

(4). filename.sh(和source一样,也是使用当前进程执行)

[root@localhost day1]# . method.sh 
hello

6.设置vim编辑sh文件的缩进为4个空格

#方法1:
[root@localhost ~]# vim ~/.vimrc   
set tabstop=4   #在文件后添加
#方法2:(推荐)
[root@localhost ~]# vim ~/.vimrc   
autocmd FileType sh setlocal ai ts=4 sw=4 et   #可以进行文件类型的修改,也可以自定义缩进的空格

#验证
创建一个sh文件,测试一下tab键

7.shell中的引用(引号的作用)

在bash中有很多特殊字符,这些特殊字符就具有特殊含义。引用就是通知shell将这些特殊字符当作普通
字符来处理。

符号说明
转义字符“\”如果将\放到特殊字符前面,shell就忽略这些特殊字符的原有含义,把它们当作普通字符对待
单引号如果将字符串放到一对单引号之间,那么字符串中所有字符的特殊含义被忽略
双引号双引号的引用与单引号基本相同,包含在双引号内的大部分特殊字符可以当作普通字符处理,但是仍然有一些特殊字符保留自己的特殊含义,比如”$“和“\”以及“ ` ”
.反向引号( )在执行时,shell 首先执行该命令行,并以它的标准输出结果取代整个反引号(包括两个反引号)部分。 注:命令替换是指shell能够将一个命令的标准输出插在一个命令行中任何位置。位于键盘Tab键上面一行的键,用作命令替换(相当于$(…))
[root@localhost ~]# echo $USER
root
[root@localhost ~]# echo "user is $USER"   #双引号
user is root
[root@localhost ~]# echo 'user is $USER'   #单引号
user is $USER
[root@localhost ~]# echo `echo user is $USER`	#反引号
user is root
[root@localhost ~]# echo ` user is $USER`         
bash: user: command not found...

[root@localhost ~]# echo "user is '$USER' "
user is 'root' 
[root@localhost ~]# echo 'user is "$USER"'
user is "$USER"
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值