Shell 学习
因为希望做一个 stable-diffusion 一键安装脚本,所以开始学习 shell ,记录下自己学习过程。同时发现想在服务器上实现一次跑完所有文件,用 bash 也是最方便的。今天先学了最简单的操作,不追求鲁棒性的话,基本上已经够用了(这里顺便吐槽下鲁棒性,是哪个大帅逼发明的翻译啊,老老实实翻译稳健性它不好吗。。。)
第一个 Shell 脚本
#!/bin/bash
echo "hello world!"
#!
是一个约定标记,告诉系统这个脚本要什么解释器来执行,即用哪一种 Shell。
echo
用于向窗口输出文本。
Shell 变量
- 定义变量时,变量名不加
$
( 这和 PHP 不一样,PHP 中变量需要 )。命名规则和其他语言相同。
your_name="Nobody"
注意:变量名和等号之间不能有空格
-
除了显示赋值以外,还可以用语句给变量赋值,如:
for file in 'ls /etc' #or use this for file in $(ls /etc)
-
使用变量
your_name="nobody" echo $your_name echo ${your_name}
以上两种方法都可以,但个人比较喜欢第二种加花括号的写法,首先这更符合
{这是一个变量}
的直觉,其次是适用性更广,比如:for skill in Ada Coffe Action Java; do echo "I am good at ${skill}Script" done
在上面那种场景下就必须要加花括号了。
-
设置变量为只读(相当于设置
const
变量)#!/bin/bash myUrl="https://jerryhouse.cn" readonly myUrl myUrl="https://www.jerryhouse.cn"
运行上述脚本会报错
/home/ljy/shell_learn/hello_world.sh: 行 24: myUrl: 只读变量
-
删除变量
unset variable_name
-
Shell 字符串
字符串是shell编程中最常用最有用的数据类型(除了数字和字符串,也没啥其它类型好用了),字符串可以用单引号,也可以用双引号,也可以不用引号。
- 单引号
str='this is a string'
单引号字符串的限制:
-
单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的;
-
单引号字串中不能出现单独一个的单引号(对单引号使用转义符后也不行),但可成对出现,作为字符串拼接使用。
-
双引号
your_name="nobody" str="Hello, I know you are \"$your_name\"! \n" echo -e $str # -e 开启转义
双引号的优势:
- 双引号里可以有变量
- 双引号里可以出现转义字符
-
字符串拼接
your_name="nobody" # 双引号拼接 greeting="hello, "$your_name"! " greeting_1="hello, ${your_name}! " echo ${greeting} ${greeting_1} # 单引号拼接 greeting_2='hello, '$your_name'! ' greeting_3='hello, ${your_name}! ' echo $greeting_2 $greeting_3
-
获取字符串长度
string="abcd" echo ${#string} # 输出 4
变量为数组时,
${#string}
等价于${#string[0]}
:string="abcd" echo ${#string[0]} # 输出 4
-
提取子字符串
以下实例从字符串第 3 个字符开始截取 4 个字符:
string="I'm nobody" echo ${string:2:4} # 输出 m no
-
查找子字符串
查找字符 i 或 o 的位置(哪个字母先出现就计算哪个):
string="I'm nobody" echo
expr index "$string" io
# 输出 6注意: 以上脚本中 ` 是反引号,而不是单引号 ',不要看错了哦。
-
Shell 数组
经过测试,这个数组支持
map<string,string>
类型bash支持一维数组(不支持多维数组),并且没有限定数组的大小。类似于 C 语言,数组元素的下标由 0 开始编号。获取数组中的元素要利用下标,下标可以是整数或算术表达式,其值应大于或等于 0
在 Shell 中,用括号来表示数组,数组元素用"空格"符号分割开。定义数组的一般形式为:
数组名=(值1 值2 ... 值n)
例如:
array_name=(value0 value1 value2 value3)
或
array_name=( value0 value1 value2 value3 )
还可以单独定义数组的各个分量:
array_name[0]=value0 array_name[1]=value1 array_name[n]=valuen
可以不使用连续的下标,而且下标的范围没有限制。
-
读取数组
读取数组元素值的一般格式:
${数组名[下标]}
例如:
valuen=${array_name[n]}
使用
@
符号可以获取数组中的所有元素,例如:echo ${array_name[@]}
-
获取数组的长度
# 取得数组元素的个数 length=${#array_name[@]} # 或者 length=${#array_name[*]} # 取得数组单个元素的长度 lengthn=${#array_name[n]}
-
Shell 注释
以 # 开头的行就是注释,会被解释器忽略。
通过每一行加一个 # 号设置多行注释,像这样:
#-------------------------------------------- # 这是一个注释 # author:ljy # site:www.jerryhouse.com # moto:总是追求不平凡,又怎能享受平凡的快乐呢 #-------------------------------------------- ##### 用户配置区 开始 ##### # # # 这里可以添加脚本描述信息 # # ##### 用户配置区 结束 #####
多行注释:
:<
Shell 传递参数
向脚本传递三个参数,并分别输出,其中 $0 为执行的文件名(包含文件路径):
#!/bin/bash
echo "Shell 传递参数实例!";
echo "执行的文件名:$0";
echo "第一个参数为:$1";
echo "第二个参数为:$2";
echo "第三个参数为:$3";
运行 ./hello_world.sh first second third
输出:
Shell 传递参数实例!
执行的文件名:./hello_world.sh
第一个参数为:first
第二个参数为:second
第三个参数为:third
运行 ~/文档/shell_learn/hello_world.sh first second third
输出:
Shell 传递参数实例!
执行的文件名:/home/ljy/文档/shell_learn/hello_world.sh
第一个参数为:first
第二个参数为:second
第三个参数为:third
PS: 学到这里,我想起来了我的右键菜单里的 Open in vscode
脚本,里面的内容如下:
#!/bin/bash
code ./$1
明白了作用就是把选中的文件或文件夹作为参数传给这个命令。 $0
的作用就是返回正在执行的脚本文件的文件名(包含路径)。例如我在终端里直接输入命令
echo $0
得到的输出为:
bash
因为终端里用的环境变量 bash
在执行这条语句。
于是我仿照这段代码写了 Open in typora
:
#!/bin/bash
typora $1
事实上,./
可加可不加,因为这条命令会默认从当前工作目录去寻找这个文件,当你右键点击要打开的文件一定是在这个目录里的。
一些处理参数的特殊字符:
参数处理 | 说明 |
---|---|
$# | 传递到脚本的参数个数 |
$* | 以一个单字符串显示所有向脚本传递的参数。如"\$*"用「"」括起来的情况、以"\$1 $2 … $n"的形式输出所有参数。 |
$$ | 脚本运行的进程号 |
$! | 后台运行的最后一个进程号(暂时没搞懂是啥意思,也许是这个脚本会后台运行程序,返回最后一个程序后台运行时的进程号) |
$@ | 与\$*相同,但是使用时加引号,并在引号中返回每个参数。 如"\$@"用「"」括起来的情况、以"\$1" "\$2" … "\$n" 的形式输出所有参数。 |
$- | 显示Shell使用的当前选项,与set命令功能相同(暂时没搞懂,终端中使用后输出为 himBHs ) |
$? | 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。 |
\$* 与 \$@ 区别:
- 相同点:都是引用所有参数。
- 不同点:只有在双引号中体现出来。假设在脚本运行时写了三个参数 1、2、3,,则 " * " 等价于 "1 2 3"(传递了一个参数),而 "@" 等价于 "1" "2" "3"(传递了三个参数)。
#!/bin/bash
echo "-- \$* 演示 ---"
for i in "$*"; do
echo $i
done
echo "-- \$@ 演示 ---"
for i in "$@"; do
echo i
done
执行 :
./hello_world.sh first second third four five
输出:
-- $* 演示 ---
first second third four five
-- $@ 演示 ---
first
second
third
four
five
叨叨几句... 1 条评论
Jerry 博主
这个主题的 markdown 渲染器代码块的渲染有点问题,之前也出现过类似问题,等我找个时候有空看能不能去换一个。多行注释那里没渲染出来。