ACWING y总的Linux基础课,看讲义作作笔记。
tmux 可以干嘛?
tmux可以分屏多开窗口,可以进行多个任务,断线,不会自动杀掉正在进行的进程。
tmux – session(会话,多个) – window(多个) – pane(最小单位shell 对话框)
ps: 原本tmux默认操作的(前缀键)是 ctrl + b Y总的AC terminal里面改成了默认ctrl+a,下面的代码里特意加以区分 特此说明
操作
直接输入tmux 将进入一个session,其中包含1个Window,Window中包含了一个pane,pane中打开一个shell对话框
pane分屏
ctrl + b 组合 % //纵向分屏
ctrl + b 组合 " //横向分屏
挂起
ctrl + b 组合 d
关闭
ctrl + d
产看所有终端
tmux ls
恢复某个挂起终端
tmux a -t name //如果没有name参数则默认挂起那个最近一次挂起的终端
给某个终端重命名
tmux rename -t oldnam newname
tmux 切换session
tmux -s
某个pane全屏/退出全屏
ctrl + b 组合 z //也许是zoomin/zoomout
切换session 及 window
ctrl + b 组合 s/w //s–session w–window
tmux中的复制粘贴
首先选中操作需要按住shift键
选中之后,按住ctrl + insert 进行复制
粘贴 shift + insrt (windows)
vim是一个文本编辑器
可以根据文件扩展名自动识别编程语言,支持代码缩进,代码高亮等功能。
使用方式:
vim filename
- 如果不存在,那么创建一个新的filename文件并打开。
- 如果存在,那么直接打开该文件并对齐进行编辑。
vim有三个模式
vim操作:
一般命令模式下
- i进入编辑模式
- hjkl 四个键分别向左,下,上,右四个方向移动光标
- n n表示数字,摁下数字再按空格,可以向右移动这一行的n个字符 移动到该字符的后一位
- 0 或者 [HOME] 回到这一行的开头
- $ 或者 [END] 光标移动到这一行的末尾
- G 光标移动到最后一行
- :n 或者 nG 表示光标移动到第n行
- gg 光标移动到第一行 相当于 1G
- n 光标向下移动n行
- /word 向光标之下查找第一个值为word的字符串
- ?word向光标之上查找第一个值为word的字符串
- n 重复前一个查找操作
- N 反向重复前一个查找操作
- :n1,n2s/word1/word2/g n1 n2为数字,意思是在n1行与n2行之间寻找word1这个单词并将该字符串替换为word2
- :1,$s/word1/word2/g 将全文的word1替换为word2
- :1,$s/word1/word2/gc 将全文的word1替换为word2 ,替换前需要用户确认
- v 选中文本
- d 删除选中文本
- dd 删除当前行
- y 复制选中的文本
- yy 复制当前行
- p 将复制的数据在光标的下一行粘贴,如果复制的是文本,那么粘贴在下一个位置;如果是yy复制的一行,那么将粘贴在下一行
- u 撤销
- ctrl + r 取消撤销
- shift + > 选中的文本整体右移
- :w 保存
- :w! 强制保存
- :set paste 设置成粘贴模式,取消代码自动缩进
- set nopaste 取消粘贴模式,开启代码自动缩进
- :set nu 显示行号
- :set nonu 关闭显示行号
- gg=G 将全文格式化,比如代码的缩进有问题,所以可以用来格式化 = 代表格式化
- ggdG 将全文删除 gg首先回到开头,d开启删除模式,G一直删除到最后一行
- :noh 关闭查找词高亮
- ctrl + q 当vim卡死的时候,可以取消当前在执行的命令
SHELL是什么?
shell是用户通过命令行与操作系统进行沟通的语言
它可以直接在命令行中执行,也可以将一套逻辑组织成一个文件,方便复用。
可以把命令行中看作是一个shell脚本在逐行执行。
Linux系统中一般默认shell语言为bash
在文件的开头需要写#! /bin/bash
这一行的作用是指明将bash脚本作为脚本解释器
解释型语言,比如python,它们不需要编译,即写即用
#! /bin/bash
echo "Hello World!"
bash脚本的执行
#
是bash文件中的注释 单行的
多行注释
:<<EOF
11
11 都是注释
11
EOF
EOF也是可以换成其他字符串的,比如abc
也可以使用!代替EOF
定义变量
#变量一般都是字符串,定义变量不需要$符号
name1 = 'abc' #可以用''
name2 = "abc" #可以用""
name3 = abc #甚至可以不加任意引号
使用变量
使用变量需要加上$
或者 ${}
花括号是可选的,主要作用是帮助解释器识别变量边界
name = abc
echo $name #输出abc
echo ${name} #输出abc
echo ${name}def #输出abcdef
只读变量
将一个变量声明为只读变量,这样后续就不可以再对它进行更改 类似c++ const的效果
name = abc
readonly name
declare -r name #两种写法均可
name = abc #将报错,因为此时的name是只读的,不可做左值
删除变量
name = abc
unset name
echo $name #将输出空
变量类型
自定义变量(局部变量)
子进程不能访问的变量
环境变量(全局变量)
子进程可以访问的变量
自定义变量修改为全局变量
name = abc #定义变量
export name #方法一
declare -x name #方法二
环境变量变为自定义变量
export name = abc #定义 环境变量
declare +x name #改为自定义变量
字符串可以用单引号修饰,也可以用双引号修饰(也可以不用引号修饰,等同用双引号修饰)
单引号与双引号的区别
name = abc
echo 'hello , $name \"hh\"' # 输出 hello , $name \"hh\"
echo "hello , $name \"hh\"" #输出hello , abc hh
获取字符串的长度
name = "abc"
echo ${#name} #将输出3
提取子串
name = "hello , abc"
echo ${name:0:5} #题去从0开始的5个字符
文件参数变量
在执行shell脚本时,可以向脚本传递参数,$1
是第一个参数$2
是第二个参数,以此类推,特殊的,$0
是文件名(包含路径)
创建文件test.sh
#! /bin/bash
echo "文件名:"$0
echo "第一个参数:"$1
echo "第二个参数:"$2
echo "第三个参数:"$3
echo "第四个参数:"$4
./test.sh 3 4 5 6
意为将3 4 5 6 作为脚本的第1 2 3 4个参数传递给脚本
类似latex语法,超过一位的数字应当用{}括起来,否则将引起歧义
参数 | 说明 |
---|---|
$# |
代表文件传入的参数个数(返回一个数字,这个数字是所有传入参数的个数) |
$* |
由所有参数构成的用空格隔开的字符串 “$1 $2 $3 $4” |
$@ |
每个参数分别用双引号括起来的字符串"$1" “$2” “$3” “$4” |
$$ |
脚本您当前运行状态的进程ID |
$? |
上一条命令的退出状态(不是stdout 而是exit code) 0代表正常退出,其他值都代表错误 |
$(command) |
返回command这条命令的stdout |
`command` | 返回command这条命令的stdout |
数组中可以存放多个不同类型的值,只支持一维数组,在初始化时不需要知名数组大小。数组下标从0开始,但是注意,可以跳着赋值,比如只赋 0 1 5 但最终实际上数组的内容只有3个
定义
数组用小括号表示,元素之间用空格隔开
array = (1 abc "def" sss)
也可以直接定义数组中某个元素的值
array[0] = 1
array[1] = abc
array[2] = "def"
arrray[3] = sss
读取数组中某个元素的值
格式
${array[index]}
读取整个数组的值
实际上@ * 都是全部的意思
array = (1 abc "def" sss)
echo $(array[@]) #第一种写法
echo ${array[*]} #第二种写法
数组的长度
也是类似字符串的 两种写法
echo{#array[@]}
echo{#array[*]}
expr
命令用户求表达式的值,格式为
expr 3+4
表达式说明
stdout
为1,否则为0exir code
: 如果为逻辑关系表达式,且表达式结果为真,exit code
为0,否则为1;如果为其他表达式,则exitcode为0字符串表达式
表达式 | 表达式释义 |
---|---|
length STRING | 返回STRING的长度 |
index STRING CHARSET | CHARSET中任意单个字符在STRING中最前面的字符位置,下标从1开始 如果STRING中完全不存在CHARSET中的字符,将返回0 |
substr STRING POSITION LENGTH | 返回STRING字符串中从POSITION开始长度最大为LENGTH的子串,如果POSITION或LENGTH为负数,0,或者非数值,则返回空字符串 |
整数表达式
expr支持普通的算数操作,算数表达式优先级低于字符串表达式,但高于逻辑关系式
逻辑表达式
或 和 与 两个
如果第一个参数非空且非0,则返回第一个参数的值,但要求第二个参数的值也是非空或非0的,否则将返回0。如果第一个参数非空且非0,那么将直接返回第一个值 ,这样的话第二个值就不参与计算(短路原则)
如果a b 都是非空且非0 那么返回第一个参数,否则将返回0。如果第一个参数为空或者0,将不会计算第二个参数
比较两端的参数,如果为true则返回1,否则返回0 “==” 是 "="的同义词,"expr"会先尝试将两端参数转换为整数,并做算数比较,如果转换失败,则按字符集排序规则做字符比较。有时候可以用 单引号’’ 将>=括在一起,避免bash将>认作关键字。
SHELL最最主要的功能是用来处理文件的,所以数值运算并不是它的主场。功能拉跨也是可以想象的
read命令用于从标准输入中读取单行数据
参数:
-p 后面可以接提示信息
-t 后面根秒数,定义输入字符的等待时间,当超过等待时间后会自动忽略此命令
read -p "this is prompt" var # 将输出提示字符串,并等待读入,被写入var中
read -t 5 var #将等待5s读入,如果无操作,那么将忽略此命令
echo 用于输出字符串
echo STRING
echo "Hello World!" # 输出普通字符串
echo Hello World! #双引号是可以忽略的(无双引号等同于双引号,双引号内的内容将转义,或取变量转换等;单引号内不会)
echo "\"Hello World \"" # 显示转义字符串
echo \"Hello World\" #也可以省略双引号的
name = abc
echo "My name is $name" #输出 My name is abc 双引号内进行了变量准换操作
echo -e "Hi \n jl" #-e 开启转义(斜杠符号),Hi的最后会输出一个换行符
echo -e "hello \c"
echo there #这是因为echo指令的最后会默认附带一个换行符,所哟两行echo之间一定会换行,那么使用\c语句可以让此输入连续,不换行
echo "Hello World" > output.txt #显示结果重定向,将内容以覆盖的形式输出到output.txt中
name = abc
echo '$name\"' #由单引号引起,那么不会转义也不会读取变量,原样输出$name\"
echo `date` #显示命令的执行结果 输出当前时间日期
#`command`用法等同于$(command)
printf
命令用于格式化输出,类似于C/C++中的printf函数
默认不会再字符串末尾添加换行符
printf format -string [arguments...]
printf "%10d\n" 123 #占十位,右对齐,如果不够10位的话在左边补空格
printf "%-10.2f!\n" 123.123321 #占十位,保留两位小数,左对齐(保留的时候是四舍五入)
printf "My name is %s\n" "abc" #格式化输出字符串
printf"%d * %d = %d\n" 2 3 `expr 2 \* 3` # 表达式的值作为参数
&&
表示与 ||
表示或
二者都具备短路原则:
expr1 && expr2 :若expr1为假,则忽略expr2
expr1 || expr2 :若expr1为真,则忽略expr2
表达式的exit code为0 表示真,非0 表示假
test用于判断文件类型,以及对变量做比较
test命令用exit code返回结果,而不是用stdout,0表示真,非0表示假
expr用的是stdout来返回结果
test 2 -lt 3 #为真,因为返回值为0
echo $? #输出上一个命令的返回值,将输出0
test -e test.sh && echo "exist" || echo "Not exist" #若文件存在,&&左值返回0 为真,执行右边打印"exist",然后返回仍然为真,那么||左值为真,不再执行右边打印"Not exist"的命令
测试参数 | 代表意义 |
---|---|
-e | 文件是否存在 |
-f | 是否为文件 |
-d | 是否为目录(文件夹) |
测试参数 | 代表意义 |
---|---|
-r | 文件是否可读 |
-w | 文件是否可写 |
-x | 文件是否可执行(当前用户) |
-s | 是否为非空文件 |
测试参数 | 代表意义 |
---|---|
-eq | 相等 |
-ne | 不等 |
-gt | 大于 |
-lt | 小于 |
-ge | 大于等于 |
-le | 小于等于 |
测试参数 | 代表意义 |
---|---|
test -z STRING | 若STRING为空,返回TRUE |
test -n STRING | 若STRING非空,返回TRUE (-n可省略) |
test str1 == str2 | str1 是否等于 str2 |
test str1 != str2 | str1 是否不等于 str2 |
测试参数 | 代表意义 |
---|---|
-a | 两条件是否同时成立 |
-o | 两条件是否至少一个成立 |
! | 取反 |
[]
用法与 test
几乎是一致的,更常用在if语句中,[[]] 是 [] 的加强版,能支持更多的特性
用方框把test的执行语句括起来就行
[]
中的每一项都要用空格隔开$
符号的时候,将进行变量名的替换,如果不用双引号括起来,如果有空格,可能会引起歧义)if … then 形式
类似 c++ if…else
if condition
then
state1
state2
...
fi
a=3
b=4
if ["$a" -lt "$b"] && ["$a" -gt 2]
then
echo ${a}在范围内
fi
if condition
then
state1
state2
...
else
state1
state2
...
fi
if condition
then
state1
state2
...
elif condition
then
state1
state2
...
else
state1
state2
...
fi
类似switch语句
case $变量名称 in
值1)
state1
state2
...
;; #类似 break
值2)
state1
state2
...
;;
*) #类似default语句
state1
state2
...
;;
esac
#用var来枚举后续每个空格隔开的元素,并操作(范围for循环)
for var in val1 val2 val3
do
state1
state2
state3
...
done
#输出 a 2 cc 每个元素自占一行
for i in a 2 cc
do
echo $i
done
#输出当前路径下的所有文件名,每个文件名占一行
for file in `ls`
do
echo $file
done
# 输出1~10
for i in $(seq 1 10) # seq命令将返回由区间范围内的值,并用空格隔开 {注意是仅限数字的}
do
echo $i
done
# 使用花括号表示范围
for i in{a..z}
do
echo $i
done
for((expression; condition; expression))
do
state1
state2
...
done
while condition
do
state1
state2
...
done
#文件结束符为ctrl+d,输出文件结束符以后read指令返回false
while read name #read命令读到文件结束符EOF后,exit code为1,否则为0;
do
echo $name
done
#当条件为真时结束
until condition
do
state1
state2
...
done
# 当用户输入yes或者YES时结束,佛瑞泽一直等待读入
until [ "${word}" == "yes" ] || [ "${word}" == "YES" ]
do
read -p "Please input yes/YES to stop this program:" word
done
跳出当前一层循环,break不能跳出case语句,跳出case语句用的是 ;;
# 读入非EOF的字符串,会输出一遍1~7,,可以通过输入ctrl+d文件结束符来结束,也可以直接用ctrl+c杀掉进程
while read name
do
for ((i=1;i<=10;i++))
do
case $i in
8)
break #跳出最近一层循环(for循环)
;; #跳出case语句
*)
echo $i
;;
esca
done
done
跳过这次循环,但不会退出循环
# 输出1~10之间所有的奇数
for ((i=1;i<=10;i++))
do
if [ `expr $i % 2` -eq 0 ]
then
continue
fi
echo $i
done
死循环的处理方式
ctrl+c 关闭
或者
ps aux #返回所有正在运行的进程
bash中的函数类似于C/C++中,但return的返回值与C/C++不同。返回的是exit code 取值为0-255,0表示正常结束
如果想要获取函数的输出结果,可以通过echo输出到stdout中,然后通过$(sunction_name)
来获取stdout中的结果
函数的return值可以通过$?
来获取
[function] fun_name(){ #function关键字可以省略
state1
state2
...
}
func(){
name = abc
echo "Hello $name"
}
func
#输出 Hello abc
不写 return时,默认 return 0
func(){
name=abc
echo "Hello $name"
return 123
}
output=$(func)
ret=$?
echo "output = $output"
echo "return = $ret"
#输出
# output = Hello abc
# return = 123
在函数内,$1
表示第一个输入参数,$2
表示第二个输入参数,,以此类推
注意: 函数内的$0
仍然是文件名,不是函数名
func() { # 递归计算 $1 + ($1 - 1) + ($1 - 2) + ... + 0
word=""
while [ "${word}" != 'y' ] && [ "${word}" != 'n' ]
do
read -p "要进入func($1)函数吗?请输入y/n:" word
done
if [ "$word" == 'n' ]
then
echo 0
return 0
fi
if [ $1 -le 0 ]
then
echo 0
return 0
fi
sum=$(func $(expr $1 - 1))
echo $(expr $sum + $1)
}
echo $(func 10)
# 输出 55
可以在函数内定义局部变量,作用范围仅在当前函数内
可以在递归函数中定义局部变量
local 变量名=变量
#! /bin/bash
func(){
local name=abc
echo $name
}
func
echo $name
# 输出 abc
# 输出 空
exit
命令用来退出当前shell进程,并返回一个退出状态,使用$?
可以接受这个退出状态
exit
命令可以接受一个正数之作为参数,代表篇退出状态,如果不指定,默认状态值是0
exit
退出状态只能是一个介于0~155之间的整数,其中只有0表示退出成功,其他值都表示失败
#! /bin/bash
if [ $# -ne 1]
then
echo "arguments not valid" #参数是不合法的
exit 1
else
echo "arguments valid"
exit 0
fi
每个进程默认会打开三个文件描述符
stdin
标准输入,从命令行读取数据,文件描述符为0stdout
标准输出,向命令行输出数据,文件描述符为1stderr
标准错误输出,向命令行输出数据,文件描述符为2可以用文件重定向将这三个文件重定向到其他文件中
命令 | 说明 |
---|---|
command > file |
将stdout 重定向到file 中 |
command < file |
将stdin 重定向到file中 |
command >> file |
将stdout 以追加方式重定向到file 中 |
command n> file |
将文件描述符 n 重定向到file 中 |
command n>> file |
将文件描述符 n 以追加方式重定向到file 中 |
echo -e "Hello \c" > ouput.txt
echo "World" >> output.txt
read str < output.txt
echo $str
创建bash脚本
#! /bin/bash
read a
read b
echo $(expr "$a" + "$b")
#执行以下命令
./test.sh < input.txt > output.txt
#将从input.txt文件中读入a,b 并最终将结果输出定向到output.txt中,而且标准输入,输出的定向顺序是可以反过来的,非常神奇
类似 include ,bash也可以引入其他文件中的代码
. filename #点与文件之间存在一个空格
或者
source filename
#eg
#创建文件test1.sh
#! bin/bash
name=abc #定义变量name
#创建文件test2.sh
#! bin/bash
source test1.sh
echo My name id : $name
用户在登陆的时候,将首先默认执行一遍bashrc中的内容,在修改了bashrc之后,需要进行source操作,什么用?
就是执行一遍bashrc,然后更改的环境变量等内容 生效.