Home Shell学习
Post
Cancel

Shell学习

shell语法不多,不算难,这里作为一项硬技能,自己总结一下。主体内容来自于菜鸟教程

shell变量

定义变量时,变量名和等号之间不能有空格

1
your_name="runoob.com"

使用变量加美元符号,变量名外面的花括号从语法层面上是可选的,加不加都行。不过加上可以帮助解释器识别变量的边界。

1
2
echo $your_name       # "runoob.com"
echo ${your_name}     # "runoob.com"

数组

Bash Shell 只支持一维数组(不支持多维数组),数组元素的下标由 0 开始,Shell 数组用括号来表示,元素用”空格”符号分割开。

定义数组:

1
2
3
4
array=(value1 value2 ... valuen)

# example
array=(1 2 3 4)

索引数组:

1
${array[index]}

获取数组的所有元素:

1
2
3
4
5
6
${array[@]}

# demo
array=(1 2 3 4)
echo ${array} # 1
echo ${array[@]} # 1 2 3 4

获取数组的长度:

1
${#array[@]}

遍历数组:

1
2
3
for v in ${array[@]}; do
  echo "${v}";
done

字符串

定义字符串可以用单引号,也可以用双引号。

1
2
str1='string1'
str2="string2"

拼接字符串,写在一起即可

1
2
str3=${str1}${str2}
echo str3      # string1string2

获取字符串长度

1
echo ${#str1}

提取子字符串,语法为${variable:offset:length}

1
2
string="welcome"
echo ${string:1:4} # 从index为1的位置开始,读取4个元素。输出 elco

字符串运算符

1
2
3
4
5
6
a="abc"
b="efg"

[ $a = $b ] # 判断是否相等,返回 false。
[ $a != $b ] # 判断是否不等,返回 true。
# 更多运算符参见https://www.runoob.com/linux/linux-shell-basic-operators.html

向shell脚本传入参数

使用$获取传入的参数。$1表示第一个参数,$2表示第二个参数… ($0是执行的bash脚本路径)

示例:

建立test.sh如下

1
2
3
4
#!/bin/bash
echo "脚本路径: $0"
echo "第一个参数: $1"
echo "第二个参数: $2"

执行

1
./test.sh 1 2

得到输出:

1
2
3
脚本路径: path/to/test.sh
第一个参数: 1
第二个参数: 2

获取更多传入参数的信息,参见菜鸟教程-Shell 传递参数

基本运算符

参见菜鸟教程-Shell 基本运算符

算术运算符

原生bash不支持简单的数学运算,可借助expr实现。

1
2
3
4
5
6
a=2
b=2
echo "两数之和为 : `expr $a + $b`"
echo "两数之差为 : `expr $a - $b`"
echo "两数之积为 : `expr $a \* $b`"   # 注意,单纯的*会报语法错误,要用\*
echo "两数之积为 : `expr $a / $b`"

需要注意:

  • 完整的表达式要被 ` 包含,注意这个字符不是常用的单引号,是在 Esc 键下边的反引号。
  • 表达式和运算符之间要有空格

关系运算符

参见菜鸟教程-Shell 基本运算符

布尔运算符

参见菜鸟教程-Shell 基本运算符

let语句

let 命令是 BASH 中用于计算的工具,用于执行一个或多个表达式,变量计算中不需要加上$ 来表示变量。菜鸟教程-Linux let 命令

示例

1
2
3
4
a=1
b=2
let c=a+b  # 不用加$
echo $c    # 3

shell流程控制

分支

if

1
2
3
4
5
6
if condition
then
    command1 
    ...
    commandN 
fi

if else

1
2
3
4
5
6
7
8
if condition
then
    command1 
    ...
    commandN
else
    command
fi

if else if

1
2
3
4
5
6
7
8
9
if condition1
then
    command1
elif condition2 
then 
    command2
else
    commandN
fi

使用((...))作为判断语句。

示例

1
2
3
4
if (( $a == $b ))
then
   echo "a 等于 b"
fi

for循环

1
2
3
4
5
6
for var in item1 ... itemN
do
    command1
    ...
    commandn
done

写成一行

1
for var in item1 item2 ... itemN; do command1; ...; commandn; done;

示例

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

while循环

1
2
3
4
while condition
do
    command
done

示例

1
2
3
4
5
6
val=1
while(( $val<=5 ))
do
    echo $val
    let val++
done

break和continue

breakcontinue作为一条command出现在bash脚本中。其含义与其他语言一致。

shell函数

基本格式

1
2
3
4
5
funname()
{
    ...
    [return sth;]
}
  • 可以向函数传入参数,参见下面的示例
  • 在函数体内部,通过 $n 的形式来获取传入的参数值。$1表示第一个参数,$2表示第二个参数… ($0是执行的bash脚本路径)
  • 如果函数有返回值,则函数返回值在调用该函数后通过使用$?获得

示例

1
2
3
4
5
6
7
8
9
add(){
    echo "第一个参数为 $1"
    echo "第二个参数为 $2"

    let val=$1+$2
    return $val
}
add 1 2
echo "输入的两个数字之和为 $?"  # 3

shell输出

可用echoprintf方法。printf比较类似C语言中的printf,支持格式化输出。

参见 菜鸟教程-Shell echo命令菜鸟教程-Shell printf 命令

shell 输入输出重定向

大多数 UNIX 系统命令从你的终端接受输入并将所产生的输出发送回到您的终端。一个命令通常从一个叫标准输入的地方读取输入,默认情况下,这恰好是你的终端。同样,一个命令通常将其输出写入到标准输出,默认情况下,这也是你的终端。菜鸟教程-Shell 输入/输出重定向

将输出重定向到 file (file已经存在的内容将被清空替代)

1
command > file

将输出重定向到 file (在file结尾追加)

1
command >> file

将输入重定向到 file

1
command < file

示例

输入重定向:

1
2
3
# in.txt
1
2
1
2
3
4
5
6
7
8
9
10
11
12
# demo.sh
add(){
	read a
    echo "第一个参数为 $a"
    read b
    echo "第二个参数为 $b"

    let val=$a+$b
    return $val
}
add 
echo "输入的两个数字之和为 $?"

执行

1
2
bash ./str_demo.sh < in.txt
# 从in.txt读取输入,在终端输出结果

输出重定向:

1
2
3
4
5
6
7
8
9
10
# demo.sh
add(){
    echo "第一个参数为 $1"
    echo "第二个参数为 $2"

    let val=$1+$2
    return $val
}
add 1 2
echo "输入的两个数字之和为 $?"  # 3

执行

1
2
bash ./str_demo.sh > out.txt
# 输出将写入out.txt,而不显示在终端

当然,也可以选择性地把部分语句重定向,如

1
2
3
4
5
6
7
8
9
10
# demo.sh
add(){
    echo "第一个参数为 $1"
    echo "第二个参数为 $2"

    let val=$1+$2
    return $val
}
add 1 2
echo "输入的两个数字之和为 $?"  > out.txt

执行

1
2
bash ./str_demo.sh
# 只会把最后一句的输出重定向到out.txt

其他

Q1

加入现在有一个demo.sh文件,使用

  • bash ./demo.sh
  • sh ./demo.sh
  • ./demo.sh

这三者的区别?

答:TODO。参考https://stackoverflow.com/a/20616103/10096987

This post is licensed under CC BY 4.0 by the author.

网络推理加速的一些基础操作

tqdm常用操作