Linux-shell教程/学习

shell概念

Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁。Shell 既是一种命令语言,又是一种程序设计语言。
Shell 脚本(shell script),是一种为 shell 编写的脚本程序。
Linux 的 Shell 种类众多,常见的有:

  • Bourne Shell(/usr/bin/sh或/bin/sh)
  • Bourne Again Shell(/bin/bash)
  • C Shell(/usr/bin/csh)
  • K Shell(/usr/bin/ksh)
    一般情况下大多数默认使用BASH

第一个shell脚本

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

# 命令用于向窗口输出文本
echo "hello world!" 

允许shell脚本的方法

  1. 作为可执行程序
    保存代码为xx.sh

chmod +x ./test.sh # 使得脚本具有执行权限
./test.sh # 执行脚本

直接写test.sh使得linux系统回去PATH种寻找是否存在该文件
./指明为当前目录

  1. 作为解释器参数

/bin/sh test.sh

shell注释

以#开头的为单行注释

多行注释:

:<<EOF
注释内容...
注释内容...
注释内容...
EOF

EOF可以被替换成其他符号

:<<'
注释内容...
注释内容...
注释内容...
'

:<<!
注释内容...
注释内容...
注释内容...
!

shell变量

定义变量

your_name="runoob.com"

注意:变量名和等号之间不能有空格

变量名的命名规则:

  • 命名只能使用英文字母,数字和下划线,首个字符不能以数字开头。
  • 中间不能有空格,可以使用下划线(_)。
  • 不能使用标点符号。
  • 不能使用bash里的关键字(可用help命令查看保留关键字)。

语句给变量赋值:

for file in $(ls /ets)

使用变量

使用一个已经定义过的变量,只需要变量名前加入$美元符号

your_name='test'
echo $your_name
echo ${your_name} #花括号只是为了帮助解释器识别变量边界,不加也行,推荐加

使用才加$,二次赋值也不需要

只读变量

#!/bin/bash
myUrl="https://www.google.com"
readonly myUrl  # readonly命令
myUrl="https://www.runoob.com"

运行该脚本则会提示:This variable is read only.

删除变量

#!/bin/sh
myUrl="https://www.runoob.com"
unset myUrl
echo $myUrl

运行该脚本则没有任何输出

unset命令不能删除只读变量

变量类型

运行shell时,会同时存在三种变量:

  1. 局部变量:局部变量在脚本或命令中定义,仅在当前shell实例中有效
  2. 环境变量:所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量。
  3. shell变量:shell变量是shell程序设置的特殊变量,其中一部分是环境变量,一部分是局部变量

shell字符串

单引号原样输出
双引号解析输出,可以有变量,可以有转移字符

your_name='runoob'
str="Hello, I know you are \"$your_name\"! \n"
echo -e $str

以单引号' '包围变量的值时,单引号里面是什么就输出什么,即使内容中有变量和命令(命令需要反引起来)也会把它们原样输出。这种方式比较适合定义显示纯字符串的情况,即不希望解析变量、命令等的场景。

以双引号" "包围变量的值时,输出时会先解析里面的变量和命令,而不是把双引号中的变量名和命令原样输出。这种方式比较适合字符串中附带有变量和命令并且想将其解析后再输出的变量定义。

greeting="hello, "$your_name" !"  # 字符串和变量一起使用

获取字符串长度

string = "abcd"
echo ${#string} # 输出4

提取子字符串

string="runoob is a great site"
echo ${string:1:4} # 输出 unoo

第一个字符的索引为0

shell数组

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

定义数组

array_name=(value0 value1 value2 value3)
# 或者可以单独定义数组的各个分量
array_name[0]=value0
array_name[1]=value1
array_name[n]=valuen

可以不使用连续的下标,且下标范围没有限制

读取数组

value = ${array_name[0]}

# 使用@符号可以获取数组中所有元素
echo ${array_name[@]}

获取数组长度

# 取得数组元素的个数
length=${#array_name[@]}
# 或者
length=${#array_name[*]}
# 取得数组单个元素的长度
lengthn=${#array_name[n]}

shell传递参数

执行shell脚本时,可以向脚本传递参数,脚本内获取参数的格式为: $n
n代表脚本的第n个参数

shell脚本内容:

#!/bin/bash
echo "Shell 传递参数实例!";
echo "执行的文件名:$0";
echo "第一个参数为:$1";
echo "第二个参数为:$2";
echo "第三个参数为:$3";

为脚本添加执行权限并执行:

$ chmod +x test.sh
$ ./test.sh 1 2 3

Shell 传递参数实例!
执行的文件名:./test.sh
第一个参数为:1
第二个参数为:2
第三个参数为:3

一些特殊字符参数

参数处理 说明
$# 传递到脚本的参数个数
$* 以一个单字符串显示所有向脚本传递的参数。 如"$*"用「"」括起来的情况、以"$1 $2 … $n"的形式输出所有参数。
$$ 脚本运行的当前进程ID号
$! 后台运行的最后一个进程的ID号
$@ \(*相同,但是使用时加引号,并在引号中返回每个参数。 如"\)@"用「"」括起来的情况、以"$1" "\(2" … "\)n" 的形式输出所有参数。
$- 显示Shell使用的当前选项,与set命令功能相同。
$? 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。

$* 与 $@ 区别:

  • 相同点:都是引用所有参数。
  • 不同点:只有在双引号中体现出来。假设在脚本运行时写了三个参数 1、2、3,,则 " * " 等价于 "1 2 3"(传递了一个参数),而 "@" 等价于 "1" "2" "3"(传递了三个参数)。

shell运算符

原生的bash不支持简单的数学运算,但是可以通过其他命令实现:awk expr等
expr 是一款表达式计算工具,使用它能完成表达式的求值操作。

#!/bin/bash

val=`expr 2 + 2`
echo "两数之和为 : $val"

注意:

  1. 是反引号`
  2. 表达式和运算符之间要有空格,2+2即错误
  3. 完整的表达式需要被反引号包含

这里只简单记录感觉常用的,详细见 https://www.runoob.com/linux/linux-shell-basic-operators.html

算术运算符

#!/bin/bash
a=10
b=20

val=`expr $a + $b`
echo "a + b : $val"

val=`expr $a - $b`

val=`expr $a \* $b`

val=`expr $b / $a`

val=`expr $b % $a`

if [ $a == $b ]
then
   echo "a 等于 b"
fi
if [ $a != $b ]
then
   echo "a 不等于 b"
fi

需要注意:

  • 条件表达式要放在方括号之间 要有空格
  • 不同系统不同shell可能有区别,注意乘号*前面必须加反斜杠。但是MAC下shell不需要;MAC下expr语法为$((表达式))

关系运算符

支持数字关系运算
-eq 相等
-ne 不相等
-gt 左大右
-lt 左小右
-ge 左大于等于右
-le 左小于等于右

同样需要方括号

布尔运算符

! 非运算
-o 或运算
-a 与运算

同样需要方括号

逻辑运算符

&& 逻辑AND
|| 逻辑OR

同样需要方括号

字符串运算符

= 检测字符串是否相等 (==为数字)
!= 不相等
-z 长度为0
-n 长度不为0
$ 是否为空

同样需要方括号

文件测试运算符

-d file 是否目录
-r file 是否可读
-w 可写
-x 可执行
-s 是否为空(文件大小是否为0)
-e 是否存在

echo命令

  • 显示普通字符串
echo "It is a test"
  • 显示转义字符
echo "\"It is a test\""
  • 显示变量
#!/bin/sh
read name  # 从标准输入中读取一行,将字符的之指定给shell变量
echo "$name It is a test"
  • 显示换行
echo -e "OK! \n" # -e 开启转义
echo "It is a test"
  • 显示不换行
#!/bin/sh
echo -e "OK! \c" # -e 开启转义 \c 不换行
echo "It is a test"
  • 显示结果定向至文件
echo "It is a test" > myfile
  • 原样输出字符串,单引号
echo '$name\"'
  • 显示命令执行结果
echo `date`

使用的是反引号;或者将命令存储在变量中,echo 使用变量

pintf命令

暂时不学习,功能类似echo的输出命令。不过移植性更好,可以格式化字符

test命令

用于检测某个条件是否成立:数值、字符、文件三个方面

流程控制

https://www.runoob.com/linux/linux-shell-process-control.html
sh的流程控制不可为空,如果分支没有语句执行,则不要写

分支

if then fi
if then else fi
if then elif then else fi

写在一行内 ; 划分


case esac

case 值 in
模式1)
    command1
    command2
    ...
    commandN
    ;;
模式2)
    command1
    command2
    ...
    commandN
    ;;
esac

每个 case 分支用右圆括号开始,用两个分号 ;; 表示 break,即执行结束

循环

for

for var in item1 item2 ....
do
xxx
done

for loop in 1 2 3 4 5
do
    echo "The value is: $loop"
done

while

while condition
do
xxx
done

#!/bin/bash
int=1v
while(( $int<=5 ))
do
    echo $int
    let "int++"
done
echo '按下 <CTRL-D> 退出'
echo -n '输入你最喜欢的网站名: '
while read FILM
do
    echo "是的!$FILM 是一个好网站"
done

continue和break

shell函数

shell输出/输出重定向

命令 说明
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 之间的内容作为输入。

command1 < infile > outfile
同时替换输入和输出,执行command1,从文件infile读取内容,然后将输出写入到outfile中。


一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件:

  • 标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。
  • 标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。
  • 标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。

$ command 2>file
stderr 重定向到 file

$ command > file 2>&1
stdout 和 stderr 合并后重定向到 file
先重定向stdout到file
再重定向stderr到stdout

Here Document

Shell 中的一种特殊的重定向方式,用来将输入重定向到一个交互式 Shell 脚本或程序。

$ wc -l << EOF
    欢迎来到
    菜鸟教程
    www.runoob.com
EOF
3          # 输出结果为 3 行
$

/dev/null 文件

如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null

/dev/null 是一个特殊的文件,写入到它的内容都会被丢弃;如果尝试从该文件读取内容,那么什么也读不到。但是 /dev/null 文件非常有用,将命令的输出重定向到它,会起到"禁止输出"的效果。

shell包含文件

暂时跳过

posted @ 2021-03-02 13:05  tlamm  阅读(223)  评论(0)    收藏  举报