原文地址 zhuanlan.zhihu.com
shell/bash脚本编程
目录收起介绍我们的第一个脚本脚本解释器用户输入测试条件判断迭代语句 - 循环参数传递退出状态码逻辑操作符函数函数参数传递通配符调试
原文地址 zhuanlan.zhihu.com
对于我自己来说,学习新框架或技术的最佳方式是同时获得实践经验,在本文中,你将自己通过编写代码来学习shell脚本的基础知识!本文包含语法,shell脚本的基础知识到中级shell编程,通过这篇文章你可以学习shell的相关知识,并且通过shell来实现Unix/Linux之间的接口
介绍
您可能已经多次遇到过“脚本”这个词,但脚本的的含义是什么意思呢?简单的来说,脚本是包含一系列要执行的命令。这些命令由解释器执行。一切你可以在命令行中输入的命令,你都可以把它放到脚本中。而且,脚本非常适合自动化任务。如果你发现自己频繁重复一些命令,你可以创建一个脚本来实现它!
The Linux philosophy is ‘Laugh in the face of danger’. Oops. Wrong One. ‘Do it yourself’. Yes, that’s it.
— Linus Torvalds
我们的第一个脚本
script.sh
#!/bin/bash
echo "My First Script!"
运行脚本
$ chmod 755 script.sh # chmod +x script.sh
$ ./script.sh
好流弊 !你刚刚编写了你的第一个bash脚本。我知道你不理解这个脚本,特别对于脚本中的第一行。不要担心我将在本文中详细介绍shell脚本,在进入任何主题之前,我总是建议在脑海中形成路线图或适当的内容索引,并明确我们将要学习的内容。因此,以下是我们将在文章中讨论的一些要点。
- 脚本解释器
- 变量
- 用户输入
- 测试
- 条件判断
- 循环语句
- 脚本参数传递
- 退出状态码
- 逻辑操作符
- 函数
- 通配符
- 调试
所以,这将是我们讨论的顺序,在本文的最后,我相信你会有足够的信心编写自己的shell脚本:)
Happy Learning Guys
脚本解释器
你可以从上面脚本的第一行看到 #!/bin/bash
这行指定了你的程序将使用那个解释器,基本上是将路径引用到解释器。Linux/Unix中有很多解释器,其中一些是:bash,zsh,sh,csh和ksh等。
这里推荐一个玩命令行必须知道的一个开源项目oh-my-zsh
All the best people in life seem to like LINUX. — Steve Wozniak
查看你的系统中有那些脚本解释器
cat /etc/shells
bash: #!/bin/bash
zsh: #!/bin/zsh
ksh: #!/bin/ksh
csh: #!/bin/csh
and so on…
注意⚠️如果脚本不包含解释器,则使用你的默认shell执行命令,因此代码可能正常运行,虽然是这样,但是不推荐这样做,使用echo $SHELL
可以知道你当前使用的解释器
注释注释以#
开始,#
后面的内容会被解释器忽略,但是#!
另当别论
变量变量指向内存中的一块区域,变量有对应的变量名和值,可以存储一些可以在将来更改的数据,shell中定义变量不需要指定变量的类型
VARIABLE_
当命名一个变量是你必须记得以下几点 变量名是区分大小写的
为了方便,变量名最好大写
- 要使用变量,必须在变量前面加
$
符号
例子
#!/bin/bash
MY_
echo "Hello, I am $MY_NAME"
OR
#!/bin/bash
MY_
echo "Hello, I am ${MY_NAME}"
提示: 可以把命令执行后的输入结果赋值给一个变量
LIST=$(ls)
SERVER_NAME=$(hostname)
合法的变量名
THIS3VARIABLE=”ABC”
THIS_IS_VARIABLE=”ABC”
thisIsVariable=”ABC”
不合法的变量名
4Number=”NUM”
This-Is-Var=”VAR”
# No special character apart from underscore is allowed!
用户输入
read
命令接收键盘的输入,标准输入(Standard Input)
read -p "PROMPT MESSAGE" VARIABLE
其中PROMPT MESSAGE
为提示用户的信息,变量VARIABLE
可以保存用户的输入,可以在程序中使用该变量
#!/bin/bash
read -p "Please Enter You Name: " NAME
echo "Your Name Is: $NAME"
测试
测试主要用于条件判断。[ condition-to-test-for ]
,如[ -e /etc/passwd ]
,注意的是[]
前后必须有空格,如[-e /etc/passwd]
是错误的写法
- 文件测试操作
-d FILE_NAM # True if FILE_NAM is a directory
-e FILE_NAM # True if FILE_NAM exists
-f FILE_NAM # True if FILE_NAM exists and is a regular file
-r FILE_NAM # True if FILE_NAM is readable
-s FILE_NAM # True if FILE_NAM exists and is not empty
-w FILE_NAM # True if FILE_NAM has write permission
-x FILE_NAM # True if FILE_NAM is executable
- 字符串测试操作
-z STRING # True if STRING is empty
-n STRING # True if STRING is not empty
STRING1 = STRIN2 # True if strings are equal
STRING1 != STRIN2 # True if strings are not equal
- 算术测试操作
var1 -eq var2 # True if var1 is equal to var2
var1 -ne var2 # True if var1 not equal to var2
var1 -lt var2 # True if var1 is less than var2
var1 -le var2 # True if var1 is less than or equal to var2
var1 -gt var2 # True if var1 is greater than var2
var1 -ge var2 # True if var1 is greater than or equal to var2
条件判断
和其他编程语言一样,shell脚本也能基于条件进行判断,我们可以使用if-else
或if-elif-else
Avoid the Gates of Hell. Use Linux!
if
语句
if [ condition-is-true ]
then
command 1
command 2
...
...
command N
fi
if-else
if [ condition-is-true ]
then
command 1
elif [ condition-is-true ]
then
command 2
elif [ condition-is-true ]
then
command 3
else
command 4
fi
case
语句case
可以实现和if
一样的功能,但是当条件判断很多的时候,使用if
不太方便,比如使用if
进行值的比较
case "$VAR" in
pattern_1)
# commands when $VAR matches pattern 1
;;
pattern_2)
# commands when $VAR matches pattern 2
;;
*)
# This will run if $VAR doesnt match any of the given patterns
;;
esac
例子
#!/bin/bash
read -p "Enter the answer in Y/N: " ANSWER
case "$ANSWER" in
[yY] | [yY][eE][sS])
echo "The Answer is Yes :)"
;;
[nN] | [nN][oO])
echo "The Answer is No :("
;;
*)
echo "Invalid Answer :/"
;;
esac
迭代语句 - 循环
可以通过循环执行同一个代码块很多次
for
循环
for VARIABLE_NAME in ITEM_1 ITEM_N
do
command 1
command 2
...
...
command N
done
Example
#!/bin/bash
COLORS="red green blue"
for COLOR in $COLORS
do
echo "The Color is: ${COLOR}"
done
Another Example
for (( VAR=1;VAR<N;VAR++ ))
do
command 1
command 2
...
...
command N
done
在当前所有txt文件前面追加new
实现重命名
#!/bin/bash
FILES=$(ls *txt)
NEW="new"
for FILE in $FILES
do
echo "Renaming $FILE to new-$FILE"
mv $FILE $NEW-$FILE
done
while
循环
当所给的条件为true
时,循环执行while
里面的代码块
while [ CONNDITION_IS_TRUE ]
do
# Commands will change he entry condition
command 1
command 2
...
...
command N
done
判断条件可以是任意的测试或者命令,如果测试或命令返回0,则表示条件成立,如果为非0则退出循环,如果一开始条件就不成立,则循环永远不会执行。
如果你不知道退出状态码是什么请不要担心,我后面会告诉你