Shell

2022-10-25 15:55:25 浏览数 (1)

Shell

  • 一、简介
  • 二、语法
    • 0. 注释
    • 1. 变量
    • 2. 数组
    • 3. 传递参数
    • 4. 运算符
    • 5. 输入输出
      • 5.1 echo
    • 5.2 printf
    • 5.3 输入输出重定向
    • 6. test
    • 7. 流程控制
      • 7.1 if
      • 7.2 for
      • 7.3 while, until
      • 7.4 case
    • 8. 函数
    • 9. 文件包含
  • 三、技巧

vim调试,/{匹配字符}可以查找相应的位置,N往后查找下一个,shift N往前。

一、简介

Linux的Shell种类众多,常见的有:(一般不区分前两种)

  • Bourne Shell(/usr/bin/sh或/bin/sh)
  • Bourne Again Shell(/bin/bash)
  • C Shell(/usr/bin/csh)
  • K Shell(/usr/bin/ksh)
  • Shell for Root(/sbin/sh)
  • ……

#!告诉系统其后路径所指定的程序即是解释此脚本文件的Shell程序

./{shell-name}.sh告诉系统说,就在当前目录找。写成{shell-name}.sh通常找不到命令的,因为linux系统会去PATH里寻找有没有叫test.sh的,而只有/bin, /sbin, /usr/bin,/usr/sbin等在PATH里,你的当前目录通常不在PATH里。

  • 运行方法一
代码语言:javascript复制
chmod a  x ./test.sh  # 添加 执行权限x(读r写w执行x,用户u用户组g其他o所有人a)
./test.sh 
  • 运行方法二 直接运行解释器,其参数就是shell脚本的文件名
代码语言:javascript复制
/bin/sh test.sh

二、语法

特殊符号含义大全 两个反引号表示整体作为一个字符串处理。

0. 注释

sh里没有多行注释,只能每一行加一个#号。 建议使用{}将需要注释的代码块框起来,定义为函数的形式,模拟注释的效果。

1. 变量

变量名和等号之间不能有空格 使用一个定义过的变量,只要在变量名前面加美元符号$即可,赋值不用加 字符串可以用单引号,也可以用双引号,也可以不用引号。 双引号优点:可以有变量,可以出现转义字符。

代码语言:javascript复制
# 获取长度
echo ${#string}

# 拼接字符串"",输出:hello, matthew!
stitch_string="hello, ${your_name}!"

echo ${stitch_string:1:4} #输出ello
# `用来将很多命令的结果保存到一个变量中去

2. 数组

bash支持一维数组(不支持多维数组),并且没有限定数组的大小。

代码语言:javascript复制
array_name=(1 2 3)
array_name=(
1 
2 
3
)

# 可以不使用连续的下标,而且下标的范围没有限制
array_name[0]=value0

# 使用@或*符号可以获取数组中的所有元素
echo ${array_name[@]}  # 输出:1 2 3
# 可配合#使用,获取数组长度
echo ${#array_name[*]}  # 输出:3

3. 传递参数

脚本内获取参数的格式为:n。n 代表一个数字,1 为执行脚本的第一个参数,2 为执行脚本的第二个参数。 其中,0 为执行的文件名。

代码语言:javascript复制
# $#: 传递到脚本的参数个数
# $*: 以一个单字符串显示所有向脚本传递的参数,$@类似
echo "$*"
./test.sh 1 2 3  # 输出: 1 2 3
# "$*"等价于"1 2 3"(传递了一个参数),而"$@"等价于"1" "2" "3"(传递了三个参数)

4. 运算符

expr 是一款表达式计算工具,使用它能完成表达式的求值操作。 表达式用esc键下的反引号扩起来,条件表达式要放在[]中,并且运算符与参与运算的数之间要用空格隔开。 乘号(*)前边必须加反斜杠()才能实现。

代码语言:javascript复制
echo `expr $a   $b`
if [ $a != $b ]  # []附近也要加“空格”
  • 关系运算符

运算符

说明

-eq

检测两个数是否相等,相等返回 true

-ne

检测两个数是否相等,不相等返回 true

-gt

检测左边的数是否大于右边的,如果是,则返回 true

-lt

检测左边的数是否小于右边的,如果是,则返回 true

-ge

检测左边的数是否大于等于右边的,如果是,则返回 true

-le

检测左边的数是否小于等于右边的,如果是,则返回 true

!

非运算

-o

或运算

-a

与运算

&&

逻辑的 AND,配合[]使用

||

逻辑的 OR,配合[]使用

-z(-n)

检测字符串长度是否为(不为)0,为0返回 true

文件测试符

5. 输入输出

read 命令从标准输入中读取一行,并把输入行的每个字段的值指定给 shell 变量。

5.1 echo

-e 开启转义,n换行,c不换行。

代码语言:javascript复制
#!/bin/sh
read input
echo -e "input is:n${input}c"
echo "."

# 输入:./test.sh -> hi
# 显示:input is:
#      hi.

输入到指定文件

代码语言:javascript复制
# 将"It is a test"输出到当前目录下的"myfile"文件中
echo "It is a test" > myfile  # 可以写成“目录/文件名”的形式

原样输出字符串,不进行转义或取变量(用单引号)

显示命令执行结果

代码语言:javascript复制
echo `date`  # 反引号,date显示当前时间

5.2 printf

使用printf的脚本比使用echo移植性好。语法为printf format-string [arguments...],默认不换行。

代码语言:javascript复制
# %-10s 指一个宽度为10个字符(-表示左对齐,没有则表示右对齐),任何字符都会被显示在10个字符宽的字符内,如果不足则自动以空格填充,超过也会将内容全部显示出来。
# %-4.2f 指格式化为小数,其中.2指保留2位小数。
printf "%-10s %-4.2fn" price 12.345

5.3 输入输出重定向

命令

说明

command > file

将输出重定向到 file。

command < file

将输入重定向到 file。

command >> file

将输出以追加的方式重定向到 file。

n > file

将文件描述符为 n 的文件重定向到 file。

n >> file

将文件描述符为 n 的文件以追加的方式重定向到 file。

n >& m

将输出文件 m 和 n 合并。

n <& m

将输入文件 m 和 n 合并。

<< tag

将开始标记 tag 和结束标记 tag 之间的内容作为输入。

6. test

test 命令用于检查某个条件是否成立,它可以进行数值、字符和文件三个方面的测试。 数值、字符的判断形式同上。

参数

说明

-e 文件名

如果文件存在则为真

-r 文件名

如果文件存在且可读则为真

-w 文件名

如果文件存在且可写则为真

-x 文件名

如果文件存在且可执行则为真

-s 文件名

如果文件存在且至少有一个字符则为真

-d 文件名

如果文件存在且为目录则为真

-f 文件名

如果文件存在且为普通文件则为真

-c 文件名

如果文件存在且为字符型特殊文件则为真

-b 文件名

如果文件存在且为块特殊文件则为真

代码语言:javascript复制
cd /bin
if test -e ./bash
then
    echo '文件已存在!'
else
    echo '文件不存在!'
fi

7. 流程控制

提供了breakcontinue

7.1 if

if语句经常与test命令结合使用,如果else分支没有语句执行,就不要写这个else。

代码语言:javascript复制
if condition1
then
    command1 
elif condition2
    command2
else
	command3
fi

# 适用于终端输入
if [ $(ps -ef | grep -c "ssh") -gt 1 ]; then echo "true"; fi

7.2 for

当变量值在列表里,for循环即执行一次所有命令,使用变量名获取列表中的当前取值。

代码语言:javascript复制
for ${var} in ${item1} ${item2} ... ${itemN}
do
    command1
    command2
    ...
    commandN
done

for var in item1 item2 ... itemN; do command1; command2… done;

7.3 while, until

代码语言:javascript复制
while condition
do
    command
done

while(( $int<=5 )) do         echo $int         let "int  " done 

一般while循环优于until循环,但在某些时候—也只是极少数情况下,until循环更加有用。

7.4 case

取值后面必须为单词in,每一模式必须以右括号结束。取值可以为变量或常数。

代码语言:javascript复制
case 值 in
	模式1)
    	command1
    ;;  # 类似break
	模式2)
    	command2
    ;;
    *) # 没有匹配
    	command3
    ;;
esac

8. 函数

函数返回值在调用该函数后通过 $? 来获得。所有函数在使用前必须定义。

代码语言:javascript复制
# []内的为固定格式,其中function可选
[ function ] funname [()]
{
    action;
    [return ${int};]
}

#!/bin/bash
funWithReturn(){
    echo "这个函数会对输入的两个数字进行相加运算..."
    echo "输入第一个数字: "
    read aNum
    echo "输入第二个数字: "
    read anotherNum
    echo "两个数字分别为 $aNum 和 $anotherNum !"
    return $(($aNum $anotherNum))
}
funWithReturn
echo "输入的两个数字之和为 $? !"

9. 文件包含

Shell 也可以包含外部脚本。

代码语言:javascript复制
. filename   # 注意点号(.)和文件名中间有一空格
或
source filename

三、技巧

/dev/null:代表linux的空设备文件,所有往这个文件里面写入的内容都会丢失,俗称“黑洞” 即不显示任何信息。 放在>后面的&(&>和>&一样),表示重定向的目标不是一个文件,而是一个文件描述符。

代码语言:javascript复制
mkdir -p /opt/mateinfo/{profile,logs}  > /dev/null

# 内置的文件描述符,/dev下
1 => stdout
2 => stderr
0 => stdin
# >存在顺序问题,下述为将输出结果重定向到文件list中,此时list作为stdout,再将stderr重定向到stdout,即文件list
find /etc -name .bashrc > list 2>&1

0 人点赞