shell编写规则

本文介绍Shell脚本的基础知识,包括变量、算术运算、条件判断等核心概念,并提供了多个示例帮助理解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第一个shell script程序

#!/bin/bash
# Program:
#    this is a test shell script
# 2015/07/10    zhubinqiang     Fitst release
echo "Welcome to shell script!"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

脚本第一行 指定/bin/bash解释器执行,虽然以#开头 但不是注释

开头的是单行注释

注释

# 这是单行注释1
# 这是单行注释2
  • 1
  • 2
  • 1
  • 2

Shell里面没有多行注释,小技巧实现多行注释

COMMENT_BLOCK=




if [ $COMMENT_BLOCK ]; then =========================== echo "comment1" echo "comment2" echo "comment3" =========================== fi
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

变量

a=15
version1=$(uname -r)
version2=`uname -r`
echo $a
echo ${version1}
echo $version2
PATH="$PATH</span>:<span class="hljs-variable">$HOME/bin"
export PATH
unset a
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  1. 变量名=变量, 两边没有空格的。 空格在shell中有特殊用途,分开的话会解释成【命令 参数 参数】的形式
  2. 变量名区分大小写。 name 与 Name 是两个变量
  3. 变量有空格的话要用单引号” 或 双引号 “” 将变量内容结合起来
  4. 上式中</span>a<span>{a} 是相同效果的。使用${a} 避免出错
  5. </span>a<span>{a}。”${a}”是弱引用,输出变量值
  6. export 使变量成为环境变量
  7. unset 取消变量
  8. shell变量是不区分类型的,变量值都是字符串。Bash允许整数比较和运算操作,但变量中只有数字

算术运算

算术运算符

操作符描述
+加法运算
-减法运算
*乘法运算
/除法运算
%求余运算
**幂运算
+=加等于
-=减等于
*=乘等于
/=除等于
%=取模等于

let 运算

a=1
let a=a+1
echo $a           # 2
let a+=1
echo $a           # 3 
let "a = a + 2"
echo $a           # 5
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

$((…))运算

a=1
a=$((a+1))
echo $a
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

expr 运算

a=1
b=`expr $a + 1`
echo $b
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

if … else … 判断语句

a="hello"
if [ "$a" == "hello" ]; then
    echo "Hello, how are you."
elif [ "$a</span>"</span> == <span class="hljs-string">""</span> -o <span class="hljs-string">"<span class="hljs-variable">$a" == '?' ]; then
    echo "what?"
elif [ "$a</span>"</span> == <span class="hljs-string">'y'</span> ] || [ <span class="hljs-string">"<span class="hljs-variable">$a" == 'Y' ]; then
    echo "Yes"
else
    echo "I don't understand you."
fi
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

[ 左右两边有一个空格, == 左右两边有一个空格,] 左边有一个空格

算术与字符串测试

操作描述操作描述
算术比较中括号[…]结构字符串比较中括号[…]结构
-eq等于=/==等于
-ne不等于!=不等于
-lt小于\<小于(ASCII) *
-le小于等于
-gt大于\>大于(ASCII)*
-ge大于等于
-z字符串为空
-n字符串不为空
算术比较双括号((…))结构条件判断
>大于-a两个条件同时成立
>=大小于等于-o任何一个条件成立
<大于!
<=小于等于

*如果在双中括号[[ … ]]测试中的话,那么不需要转义符\

文件测试

操作描述操作描述
-e文件是否存在-s文件大小不为0
-f是一个标准文件
-d是一个目录-r文件具有读的权限
-h文件是一个符号链接-w文件具有写的权限
-L文件是一个符号链接-x文件具有执行权限
-b文件是一个块设备
-c文件是一个字符设备-g设置了sgid标记
-p文件是一个管道-u设置了suid标记
-S文件是一个socket-k设置了”粘贴位”
-t文件与一个终端相关联
-N从这个文件最后一次被读取之后,它被修改过F1 -nt F2文件F1比文件F2新
-O这个文件的宿主是你F1 -nt F2文件F1比文件F2旧
-G文件的组id与你所在的组相同F1 -nt F2文件F1和F2都是同一个文件的硬链接
!“非”(翻转上边的测试结果)

Case

像C语言中的switch… case…

a="hello"
case $a in
"hello")
    echo "Hello, how are you." ;;
"")
    echo "what?" ;;
*)
    echo "I don't understand you." ;;
esac
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

while 循环

i=0
s=0
while [ "$i" -le 100 ];do
    s=$((s+i))
    i=$((i+1))
done
echo "1 + 2 + 3 + ... + 100 = $s"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

until 循环

i=0
s=0
until [ "$i" -gt 100 ]; do
    s=$((s+i))
    i=$((i+1))
done
echo "1 + 2 + 3 + ... + 100 = $s"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

for 循环

for i in Tom Jack John; do
    echo $i
done

for i in $(seq 1 5); do
    echo $i
done

for i in {1..5}; do
    echo $i
done

for((i=0; i<5; i++)); do
    echo $i
done
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

数组

array=(5 4 3 2 1)
echo ${array[0]}     # 第一个元素

len=${#array[*]}     # 数组长度
for((i=0; i<$len; i++));do
    echo ${array[$i]}
done

for i in ${!array[@]}; do
    echo ${array[$i]}
done
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

函数

函数定义

function function_name {
    command...
}

function function_name() {
    command...
}

function_name() {
    command...
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

使用函数

function sayHello() {
    local name=$1
    echo "Hello $name"
    return 0
}

sayHello "Tom"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

return返回的是状态码。 0 表示成功, 非0表示失败。

如果要返回值用echo

function sum(){
    local a=$1
    local b=$2
    local s=$((a+b))
    echo $s
}

s=`sum 2 3`
echo $s
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

用shift 获取参数

function sum(){
    local a=$1
    shift
    local b=$1
    local s=$((a+b))
    echo $s
}

s=`sum 2 3`
echo $s
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

I/O操作

终端输入,并赋值

read -p "Your name(within 30s):" -t 30 named
echo $named
  • 1
  • 2
  • 1
  • 2

输出多行

cat << EOF
comment1
comment2
comment3
EOF
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

I/O重定向

COMMAND > filename             # 重定向stdout到文件filename
COMMAND 1> filename            # 重定向stdout到文件filename
COMMAND >> filename            # 重定向stdout并追加到文件filename
COMMAND 1>> filename           # 重定向stdout并追加到文件filename
COMMAND 2> filename            # 重定向stderr到文件filename
COMMAND 2>> filename           # 重定向stderr并追加到文件filename
COMMAND &> filename            # 将stdoutstderr都重定向到filename
COMMAND &>> filename           # 将stdoutstderr都重定向并追加到filename
COMMAND > filename 2>&1        # 将stdoutstderr都重定向到filename
COMMAND >> filename 2>&1       # 将stdoutstderr都重定向并追加到filename
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

管道操作

COMMAND1 | COMMAND2 | COMMAND3
cat /etc/passwd | grep "root" | awk -F":" '{print $1}' 
  • 1
  • 2
  • 1
  • 2

管道操作是由前面的stdin传递过来的。 stderr不会传过去

特殊Shell变量

变量含义
$0脚本名字
$1位置参数 #1
$9位置参数 #9
${10}位置参数 #10
$#位置参数的个数
“$*”所有的位置参数(作为单个字符串)
“$@”位置参数的个数(作为独立的字符串)
${#*}传递到脚本中的命令行参数的个数
${#@}传递到脚本中的命令行参数的个数
$?返回值
$$脚本的进程IP(PID)
$-传递到脚本中的标志(使用set)
$_之前命令的最后一个参数
$!运行在后头的最后一个作业的进程ID(PID)

@”

系统环境变量

变量含义
$IFS保存了用于分割输入参数的分割字符,默认识空格
$HOME当前用户的根目录路径
$PATH可执行文件的搜索路径
$PS1第一个系统提示符
$PS2第二个系统提示符
$PWD当前工作路径
$EDITOR系统的默认编辑器名称
$BASH当前Shell的路径字符串
$EUID“有效”用户ID

字符串操作

表达式描述
${#string}$string的长度
${string:position}在$string中,从position开始提取字串
${string:position:length}在$string中,从position开始取长度为length的字串
${string#substring}从变量</span>string<span>substring的字串
${string##substring}从变量</span>string<span>substring的字串
${string%substring}从变量</span>string<span>substring的字串
${string%%substring}从变量</span>string<span>substring的字串
${string/substring/replacement}使用</span>replacement,<span>substring
${string//substring/replacement}使用</span>replacement,<span>substring
${string/#substring/replacement}如果</span>string<span>substring,那么就用</span>replacement<span>substring
${string/%substring/replacement}如果</span>string<span>substring,那么就用</span>replacement<span>substring
expr match “</span>string<span>substring’匹配</span>string<span>substring*的长度
expr “</span>string:<span>substring’匹配</span>string<span>substring*的长度
expr index “</span>string<span>substring</span>sttring<span>substring的第一个字符出现
expr substr </span>string<span>position $length</span>string<span>position开始提取长度为$length的字串
expr match “</span>string{<span>substring}\’</span>string<span>substring*
expr “</span>string:\(<span>substring)\’</span>string<span>substring*
expr match “</span>string.\(<span>substring)\’</span>string<span>substring*
expr “</span>string:.\(<span>substring)\’</span>string<span>substring*

* $substring 是一个正则表达式

结构汇总

操作描述
中括号
if [ Condition ]测试结构
if [[ Condition ]]扩展的测试结构
Array[1]=element1数组初始化
[a-z]正则表达式的字符范围
大括号
${variable}参数替换
${!variable}间接变量引用
{ command1; command2; … commandN; }代码块
{string1, string2, string3}大括号扩展
小括号
( command1; command2 )子shell中执行的命令组
Array=(element1 element2 emement3)数组初始化
result=$(COMMAND)在子shell中执行命令,并将结果赋值给变量
>(COMMAND)进程替换
<(COMMAND)进程替换
双小括号
(( var = 78 ))整型运算
var=$(( 20 + 5 ))整型运算,并将结果赋值给变量
引号
“$variable”“弱”引用
‘string’“强”引用
后置引用
result=`COMMAND`在子shell中运行命令,并将结果赋值给变量

globbing

*: 匹配任意长度的任意字符
a*b 匹配 ab, a123b

?: 匹配任意单字符
a?b 匹配 a1b, a2b

[]: 匹配指定范围内的 任意单字符
[abc], [a-z], [0-9]

[^]: 匹配任意范围外的任意单字符
[^a-z0-9]

字符合集
[[:space:]]: 所有空白字符
[[:punct:]]: 所有标点字符
[[:lower:]]: 小写字母
[[:upper:]]: 大写字母
[[:alpha:]]: 所有字母
[[:digit:]]: 数字
[[:alnum:]]: 字母数字

举例:在/urs/lib/下列出 以l开头,中间有数字,结尾是小写字母
ls /usr/lib/l*[[:digit:]]*[[:lower:]]

echo -e '\033[32mHello\033[0m'

\033[
\033: Ctrl
单个数字:控制字体
3#: 3表示控制其前景色, #是一个数字
4#: 4表示控制其背景色, #是一个数字
组合使用,彼此间使用;分隔
m: 是固定格式
\033[0m: 控制符到此结束



(function () {('pre.prettyprint code').each(function () {
var lines = (this).text().split(\n).length;varnumbering = $('
    ').addClass('pre-numbering').hide();
    (this).addClass(hasnumbering).parent().append(numbering);
    for (i = 1; i <= lines; i++) {
    numbering.append(('
    • ').text(i));
      };
      $numbering.fadeIn(1700);
      });
      });

      这里写代码片

    Shell脚本是一种可以执行的文本文件,其中包含了一系列需要按顺序执行的命令。编写Shell脚本时,需要遵循以下规则: 1. 文件扩展名:通常,Shell脚本的文件扩展名为.sh,以便区分其他类型的文件。 2. 脚本头部:在Shell脚本的第一行,使用Shebang行来指定脚本解释器。例如,#!/bin/bash表示使用Bash解释器执行脚本。不同的Shell解释器可能有不同的Shebang行。 3. 注释:可以在脚本中使用注释来提供额外的说明。注释以#开头,可以单独一行或在命令行后面。 4. 可执行权限:在使用Shell脚本之前,需要给脚本文件添加可执行权限。可以使用chmod命令来设置脚本的执行权限,例如chmod +x script.sh。 5. 命令的书写:在Shell脚本中,每个命令都需要单独的一行,或使用分号来分隔多个命令。命令的参数可以在同一行上,也可以分行书写。 6. 变量:可以在Shell脚本中使用变量来保存数据。变量名需要以字母或下划线开头,并由字母、数字和下划线组成。变量的值可以是字符串、数字等。 7. 控制流语句:通过使用条件语句(如if语句)、循环语句(如for和while循环)和函数等控制流语句,可以实现更复杂的操作。 8. 输入输出:Shell脚本可以从标准输入(键盘)读取数据,并向标准输出(屏幕)打印结果。也可以使用重定向和管道来进行输入输出的处理。 以上是编写Shell脚本的一些基本规则。根据具体需求,还可以结合各种Shell控制语句和命令来完成更复杂的操作。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Shell编程规范](https://blog.youkuaiyun.com/weixin_45305723/article/details/123852926)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

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

    抵扣说明:

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

    余额充值