Linux Shell 学习

Linux Shell 学习

可以执行的 Shell 脚本

建立一个 shell 脚本文件,文件名为 test1.sh,内容如下:

echo "Hello world!"

写完之后要赋予可执行权限:

chmod +x test1.sh

然后就可以运行了。

变量

变量可以包含字母、数字和下划线,但不能以数字开头。变量名区分大小写。使用大写字母表示常量。

避免使用系统保留的变量名,如 PATHHOME 等。同时避免使用 $ ? 等特殊字符。

Shell 赋值等号两边不能有空格

PI=3.14159
count=0

for i in `ls /etc`; do
        let count+=1
done

echo $count

使用 let 可以进行算术运算:

let count+=1

上面这个例子中,count 的值会在每次循环中加 1,以此可以输出 /etc 目录下的文件数量。

使用 $(()) 可以进行算术运算:

count=$((count + 1))

对于浮点数的计算,Shell 本身不支持浮点数运算,可以使用 bc 命令:

PI=3.14
echo "$(echo "$PI * 2" | bc)"

输出 6.28

可以使用 readonly 来定义只读变量:

readonly PI=3.14159

可以使用 unset 来删除变量:

unset PI

特殊变量: 有一些特殊变量在 Shell 中具有特殊含义,例如 $0 表示脚本的名称,$1, $2, 等表示脚本的参数。$#表示传递给脚本的参数数量,$? 表示上一个命令的退出状态等。

字符串中,转义字符与其它大多数语言一样适用。但是 echo 命令中,转义字符可能需要使用 -e 参数才能生效。

# Test backslash
str="Let's go for \"me\". \nTry your best!"
echo -e $str

字符串拼接可以任意轻易组合:

str_out="You might say: \""${str}"\"\nThat's right!"
echo -e $str_out

需要注意的是,Shell 中使用 $ 使用变量必须跃出字符串引号。

使用 ${#} 可以获取字符串的长度:

str="Hello world!"
echo ${#str}  # 输出 12

使用 ${:-} 可以获取字符串的子串:

str="Hello world!"
echo ${str:6:5}  # 输出 world

${str:6:5} 表示从索引 6 开始,取 5 个字符。

使用 expr 可以查找字符串中某个字符的位置:

str="Hello world!"
echo `expr index "$str" o`  # 输出 5

注意: expr 只能查找单个字符的位置,不能查找字符串。如果写作 expr index "$str" "world",会查找 world 中任意字符首个出现的位置,即 3l 出现于第三个字符)。

数组

Shell 中的数组可以使用括号 () 来定义,元素之间用空格分隔:

arr1=(1 1 4 5 1 4)

或者

arr2=(
    1
    1
    4
    5
    1
    4
)

使用下标法访问数组元素:

arr1=(1 1 4 5 1 4)
echo ${arr1[2]}

输出 4

使用 @* 可以获取数组的所有元素:

echo ${arr1[@]}
echo ${arr1[*]}

二者输出是等效的。

获取数组长度的方法与获取字符串长度的方法类似:

echo ${#arr1[*]}

使用 declare -A 可以定义关联数组:

declare -A arr=(["inner"]=0 ["center"]=1 ["outer"]=0)
echo ${arr["center"]}

使用 ! 返回所有键:

echo ${!arr[@]}

输出 6

注释

单行 #,多行 :

例如:

# 这是单行注释

:<<EOF
注释注释注释
注释注释
EOF

echo 1

:<<'COMMENT'
注释
注释注释
COMMENT

:<<'
注释1
注释2
'

ls -l

:<<!
注释注释
Acceed
注释
!

:'
多行内容
字符串注释
'

传递参数

Shell 预留了一些特殊变量来获取传递给脚本的参数:

变量 含义
$0 脚本的名称
$1 第一个参数
$2 第二个参数
$# 参数的个数
$* 所有参数,作为一个字符串
$@ 所有参数,作为一个数组
$? 上一个命令的退出状态
$$ 当前 Shell 的进程 ID
$! 上一个后台命令的进程 ID

运算符

原生 Bash 不支持基本数学运算,只能使用 awkbcexpr 等工具来进行数学运算。

常用 expr 进行表达式计算,例如:

#! /bin/bash

val=`expr 1 + 2 \* 3`
echo $val

算术运算要使用 [] 确定条件,并且在 [] 内部的运算符两边必须有空格。

if [ $val < 5 ]
then
    echo "val < 5"
fi
if [ $val > 5 ]
then
    echo "val > 5"
fi

关系运算符:

运算符 含义
-eq 等于
-ne 不等于
-gt 大于
-lt 小于
-ge 大于等于
-le 小于等于

关系运算符仅支持数字。

val=10
if [ $val -eq 10 ]
then
    echo "val = 10"
fi

布尔运算符:

运算符 含义
!
-o
-a
val1=10
val2=20

if [ $val1 -eq 10 -a $val2 -eq 20 ]
then
    echo "val1 = 10 and val2 = 20"
else 
    echo "val1 != 10 or val2 != 20"
fi

逻辑运算符:

运算符 含义
&&
| |
val1=10
val2=20

if [ $val1 -eq 10 ] && [ $val2 -eq 20 ]
then
    echo "val1 = 10 and val2 = 20"
else
    echo "val1 != 10 or val2 != 20"
fi

字符串运算符:

运算符 含义
= 等于
!= 不等于
-z 字符串长度为零
-n 字符串长度不为零
$ 字符串不为空
str1="Hello world!"
str2="Hello world!"

if [ $str1 = $str2 ]
then
    echo "str1 = str2"
fi

此处运算没有使用 ==,而是使用了 =,因为 = 是字符串比较运算符,而 == 是模式匹配运算符。

文件测试运算符:

运算符 含义 记忆标记
-b file 文件存在且是块设备文件 block
-c file 文件存在且是字符设备文件 character
-d file 文件存在且是目录 directory
-e file 文件存在 exists
-f file 文件存在且是普通文件 file
-g file 文件存在且设置了 SGID 位 GID
-k file 文件存在且设置了粘滞位 sticKy
-p file 文件存在且是命名管道 pipe
-r file 文件存在且可读 readable
-s file 文件存在且不为空 size
-t fd 文件描述符存在且指向终端 terminal
-u file 文件存在且设置了 SUID 位 UID
-w file 文件存在且可写 writable
-x file 文件存在且可执行 eXecutable
-S file 文件存在且是套接字 Socket
-L file 文件存在且是符号链接 Link
#! /bin/bash

file="./test1.sh"

if [ -r $file ]
then
    echo "文件可读"
else
    echo "文件不可读"
fi
if [ -w $file ]
then
    echo "文件可写"
else
    echo "文件不可写"
fi
if [ -x $file ]
then
    echo "文件可执行"
else
    echo "文件不可执行"
fi
if [ -f $file ]
then
    echo "文件为普通文件"
else
    echo "文件为特殊文件"
fi
if [ -d $file ]
then
    echo "文件是个目录"
else
    echo "文件不是个目录"
fi
if [ -s $file ]
then
    echo "文件不为空"
else
    echo "文件为空"
fi
if [ -e $file ]
then
    echo "文件存在"
else
    echo "文件不存在"
fi

echo

选项 含义
-n 不换行输出
-e 启用转义字符

输出内容到文件:

#! /bin/bash

echo "Hello!" > ./story.txt
echo "This is a story of ..." >> story.txt

其中,使用 > 会覆盖文件内容,而使用 >> 会追加内容到文件末尾。

使用 ANSI 转义码可以实现彩色文本,但是用途不大。

printf

这是个 C 语言风格的输出函数,使用起来比 echo 更加灵活。

printf "Time now: %s\n" "$(date)"

输出:

Time now: 2026年  8月 26號 星期三 12:06:03 CST

test

用于文件测试。

基本语法如下:

test expression
选项 含义
-e 文件存在
-f 文件存在且是普通文件
-d 文件存在且是目录
-r 文件存在且可读
-w 文件存在且可写
-x 文件存在且可执行
-s 文件存在且不为空
-L 文件存在且是符号链接

例如,检测 /etc/passwd 文件基本情况:

#! /bin/bash

file="/etc/passwd"

if [ -e "$file" ]; then
    echo "$file is exist."
    if [ -r "$file" ];  then
        echo "$file can be read."
    fi
else
    echo "$file is not exist."
fi

字符串比较:

选项 含义
-z string 字符串长度为零
-n string 字符串长度不为零
string1 = string2 字符串相等
string1 != string2 字符串不相等

示例

  • 检查 nginx 服务的运行状态:
#! /bin/bash

service="nginx"

if systemctl is-active --quiet "$service"; then
    echo "$service is running."
else
    echo "$service is not running."
fi

流程控制

Shell 的流程控制有常见的几种。

if else 语句

语法:

if [ condition ]; then
    # commands
elif [ condition ]; then
    # commands
else
    # commands
fi

同时,判断条件可以使用 (()) 来进行算术比较运算,使用 [[ ]] 来进行字符串比较,也可使用 test 命令来进行比较。

for 循环

语法:

for var in list
do
    # commands
done

while 循环

语法:

while [ condition ]
do
    # commands
done

until 循环

语法:

until [ condition ]
do
    # commands
done

case 语句

语法:

case "$variable" in
    pattern1)
        # commands
        ;;
    pattern2)
        # commands
        ;;
    *)
        # commands
        ;;
esac

例如,判断输入数字作为选项:

#! /bin/bash

read num
case $num in
    1)
        echo "You chose 1."
        ;;
    2)
        echo "You chose 2."
        ;;
    3)
        echo "You chose 3."
        ;;
    *)
        echo "Illegal input."
        ;;
esac

breakcontinue

使用方法与 C 语言基本一致。

函数

函数的定义格式如下:

[function] function_name [()]
{
    # commands
    [return int;]
}

例如:

#! /bin/bash

demo() {
    echo "This is an empty funcion."
}

demo

注意: return 语句只能返回整数,而且只能返回 0 ~ 225 之间的整数。

函数获取参数的方法与脚本获取参数的方法相同,使用 $1, $2, 等表示函数的参数,而且不能在定义的时候给函数命名参数。

demo() {
    echo "This is a function with parameters."
    echo "$1 is the first parameter."
}

输入 / 输出重定向

命令 含义
command > file 将标准输出重定向到文件,覆盖原有内容
command < file 将标准输入重定向到文件
command >> file 将标准输出重定向到文件,追加内容
n > file 将文件描述符 n 重定向到文件
n >> file 将文件描述符 n 重定向到文件,追加内容
n >& m 将文件描述符 n 重定向到文件描述符 m (合并)
n <& m 将文件描述符 n 重定向到文件描述符 m (合并)
<< tag 将标准输入重定向到当前脚本中,直到遇到指定的 tag

例如,使命令不要任何的输出:

command > /dev/null 2>&1

注意:此处 2>&1 表示将标准错误输出重定向到标准输出,/dev/null 是一个特殊的设备文件,表示丢弃所有写入它的数据。2> 间不能有空格,否则 2 会被当作一个普通的文件名。

文件包含

使用 .source 包含一个 Shell。

例如 test1.sh 文件内容如下:

counter=0

test2.sh 文件内容如下:

#! /bin/bash

. ./test1.sh
echo $counter

此处,test2.sh 文件中使用 . 来包含 test1.sh 文件,从而可以访问 test1.sh 中定义的变量 counter

本文完…

参考教程:Runoob Shell 教程

本文根据此教程内容整理删减,适合具有一定基础的读者阅读,以达到快速掌握 Shell 的目的。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇