Linux基础 ——tmux vim 以及基本的shell语法

Linux 基础

ACWING y总的Linux基础课,看讲义作作笔记。

tmux

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

  1. vim是一个文本编辑器

  2. 可以根据文件扩展名自动识别编程语言,支持代码缩进,代码高亮等功能。

  3. 使用方式:

    vim filename

    1. 如果不存在,那么创建一个新的filename文件并打开。
    2. 如果存在,那么直接打开该文件并对齐进行编辑。

vim有三个模式

  1. 默认模式
    命令输入方式:按不同的操作字符,实现不同操作
  2. 编辑模式
    默认模式下按i或insert可以进入,进行文本,代码的编辑。
  3. 命令行模式
    在一般的命令模式下按下 : / ? 其中任意一个进入,可以进行查找,替换,保存,配置编辑器等等。

vim操作:

一般命令模式下

  1. i进入编辑模式
  2. hjkl 四个键分别向左,下,上,右四个方向移动光标
  3. n n表示数字,摁下数字再按空格,可以向右移动这一行的n个字符 移动到该字符的后一位
  4. 0 或者 [HOME] 回到这一行的开头
  5. $ 或者 [END] 光标移动到这一行的末尾
  6. G 光标移动到最后一行
  7. :n 或者 nG 表示光标移动到第n行
  8. gg 光标移动到第一行 相当于 1G
  9. n 光标向下移动n行
  10. /word 向光标之下查找第一个值为word的字符串
  11. ?word向光标之上查找第一个值为word的字符串
  12. n 重复前一个查找操作
  13. N 反向重复前一个查找操作
  14. :n1,n2s/word1/word2/g n1 n2为数字,意思是在n1行与n2行之间寻找word1这个单词并将该字符串替换为word2
  15. :1,$s/word1/word2/g 将全文的word1替换为word2
  16. :1,$s/word1/word2/gc 将全文的word1替换为word2 ,替换前需要用户确认
  17. v 选中文本
  18. d 删除选中文本
  19. dd 删除当前行
  20. y 复制选中的文本
  21. yy 复制当前行
  22. p 将复制的数据在光标的下一行粘贴,如果复制的是文本,那么粘贴在下一个位置;如果是yy复制的一行,那么将粘贴在下一行
  23. u 撤销
  24. ctrl + r 取消撤销
  25. shift + > 选中的文本整体右移
  26. :w 保存
  27. :w! 强制保存
  28. :set paste 设置成粘贴模式,取消代码自动缩进
  29. set nopaste 取消粘贴模式,开启代码自动缩进
  30. :set nu 显示行号
  31. :set nonu 关闭显示行号
  32. gg=G 将全文格式化,比如代码的缩进有问题,所以可以用来格式化 = 代表格式化
  33. ggdG 将全文删除 gg首先回到开头,d开启删除模式,G一直删除到最后一行
  34. :noh 关闭查找词高亮
  35. ctrl + q 当vim卡死的时候,可以取消当前在执行的命令

SHELL语法

SHELL是什么?

shell是用户通过命令行与操作系统进行沟通的语言

它可以直接在命令行中执行,也可以将一套逻辑组织成一个文件,方便复用。

可以把命令行中看作是一个shell脚本在逐行执行。

Linux系统中一般默认shell语言为bash

在文件的开头需要写#! /bin/bash 这一行的作用是指明将bash脚本作为脚本解释器

解释型语言,比如python,它们不需要编译,即写即用

bash 复制代码
#! /bin/bash
echo "Hello World!"

bash脚本的执行

  1. bash test.sh //如果用解释器来执行,那么无需权限
  2. ./bash.sh // 如果使用可执行文件来执行的话,那么需要具备可执行文件
  3. 可以用绝对路径执行,也可以在家目录下执行
注释

# 是bash文件中的注释 单行的

多行注释

bash 复制代码
:<<EOF
11
11 都是注释
11
EOF

EOF也是可以换成其他字符串的,比如abc

也可以使用!代替EOF

变量

定义变量

bash 复制代码
#变量一般都是字符串,定义变量不需要$符号
name1 = 'abc' #可以用''
name2 = "abc" #可以用""
name3 = abc #甚至可以不加任意引号

使用变量

使用变量需要加上$ 或者 ${} 花括号是可选的,主要作用是帮助解释器识别变量边界

bash 复制代码
name = abc
echo $name #输出abc
echo ${name} #输出abc
echo ${name}def #输出abcdef

只读变量

将一个变量声明为只读变量,这样后续就不可以再对它进行更改 类似c++ const的效果

bash 复制代码
name = abc
readonly name
declare -r name #两种写法均可

name = abc #将报错,因为此时的name是只读的,不可做左值

删除变量

bash 复制代码
name = abc
unset name
echo $name #将输出空

变量类型

  1. 自定义变量(局部变量)

    子进程不能访问的变量

  2. 环境变量(全局变量)

    子进程可以访问的变量

自定义变量修改为全局变量

bash 复制代码
name = abc #定义变量
export name #方法一
declare -x name #方法二

环境变量变为自定义变量

bash 复制代码
export name = abc #定义 环境变量
declare +x name #改为自定义变量

字符串

字符串可以用单引号修饰,也可以用双引号修饰(也可以不用引号修饰,等同用双引号修饰)

单引号与双引号的区别

  1. 单引号中的内容将原样输出,不会转义,不会解释,取变量等
  2. 双引号中的内容将进行转义,取变量等操作
bash 复制代码
 name = abc
 
 echo 'hello , $name \"hh\"'  # 输出 hello , $name \"hh\"
 
 echo "hello , $name \"hh\""  #输出hello , abc hh

获取字符串的长度

bash 复制代码
name = "abc"
echo ${#name} #将输出3

提取子串

bash 复制代码
name = "hello , abc"
echo ${name:0:5} #题去从0开始的5个字符

默认变量

文件参数变量

在执行shell脚本时,可以向脚本传递参数,$1是第一个参数$2是第二个参数,以此类推,特殊的,$0是文件名(包含路径)

创建文件test.sh

bash 复制代码
#! /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个

定义

数组用小括号表示,元素之间用空格隔开

bash 复制代码
array = (1 abc "def" sss)

也可以直接定义数组中某个元素的值

bash 复制代码
array[0] = 1
array[1] = abc
array[2] = "def"
arrray[3] = sss

读取数组中某个元素的值

格式

bash 复制代码
${array[index]}

读取整个数组的值

实际上@ * 都是全部的意思

bash 复制代码
array = (1 abc "def" sss)
echo $(array[@])  #第一种写法
echo ${array[*]}  #第二种写法

数组的长度

也是类似字符串的 两种写法

bash 复制代码
echo{#array[@]}
echo{#array[*]}

expr命令

expr命令用户求表达式的值,格式为

bash 复制代码
expr 3+4

表达式说明

  • 表达式需要空格隔开每一项
  • 用反斜杠放在shell特定的字符前面进行转义,防止出错
  • 对包含空格和其他特殊字符的字符串要用引号括起来,因为你操作的字符串中本身可能含有空格,这些空格可能导致expr语义出现错误
  • expr 会在stdout 中输出结果,如果为逻辑关系表达式,则结果为真,则stdout为1,否则为0
  • 同时expr的exir 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命令

read命令用于从标准输入中读取单行数据

参数:

-p 后面可以接提示信息

-t 后面根秒数,定义输入字符的等待时间,当超过等待时间后会自动忽略此命令

bash 复制代码
read -p "this is prompt" var # 将输出提示字符串,并等待读入,被写入var中

read -t 5 var #将等待5s读入,如果无操作,那么将忽略此命令

ECHO命令

echo 用于输出字符串

bash 复制代码
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命令

printf命令用于格式化输出,类似于C/C++中的printf函数

默认不会再字符串末尾添加换行符

bash 复制代码
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用于判断文件类型,以及对变量做比较

test命令用exit code返回结果,而不是用stdout,0表示真,非0表示假

expr用的是stdout来返回结果

bash 复制代码
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
bash 复制代码
if condition
then 
	state1
	state2
	...
fi
bash 复制代码
a=3
b=4
if ["$a" -lt "$b"] && ["$a" -gt 2]
then 
	echo ${a}在范围内
fi
单层if-else
bash 复制代码
if condition
then 
	state1
	state2
	...
else
	state1
	state2
	...
fi
多层if-else-else
bash 复制代码
if condition
then
	state1
	state2
	...
elif condition
then
	state1
	state2
	...
else
	state1
	state2
	...
fi
case...esac 形式

类似switch语句

bash 复制代码
case $变量名称 in
	值1)
		state1
		state2
		...
		;; #类似 break
	值2)
		state1
		state2
		...
		;;
	*) #类似default语句
		state1
		state2
		...
		;;
esac

循环语句

for...in...do...done
bash 复制代码
#用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((...;...;...)) do...done
bash 复制代码
for((expression; condition; expression))
do
	state1
	state2
	...
done
while...do...done
bash 复制代码
while condition
do
	state1
	state2
	...
done

#文件结束符为ctrl+d,输出文件结束符以后read指令返回false
while read name   #read命令读到文件结束符EOF后,exit code为1,否则为0; 
do
	echo $name
done
until...do...done
bash 复制代码
#当条件为真时结束

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命令

跳出当前一层循环,break不能跳出case语句,跳出case语句用的是 ;;

bash 复制代码
# 读入非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
continue命令

跳过这次循环,但不会退出循环

bash 复制代码
# 输出1~10之间所有的奇数
for ((i=1;i<=10;i++))
do
	if [ `expr $i % 2` -eq 0 ]
	then
		continue
	fi
	echo $i
done

死循环的处理方式

ctrl+c 关闭

或者

  1. 使用top命令找到进程的PID
  2. 输入 kill -9 PID 也可直接杀死进程

ps aux #返回所有正在运行的进程

函数

bash中的函数类似于C/C++中,但return的返回值与C/C++不同。返回的是exit code 取值为0-255,0表示正常结束

如果想要获取函数的输出结果,可以通过echo输出到stdout中,然后通过$(sunction_name)来获取stdout中的结果

函数的return值可以通过$?来获取

bash 复制代码
[function] fun_name(){ #function关键字可以省略
	state1
	state2
	...
}
不获取 return 和 stdout值
bash 复制代码
func(){
	name = abc
	echo "Hello $name"
}
func
#输出 Hello abc
获取return 和 stdout值

不写 return时,默认 return 0

bash 复制代码
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仍然是文件名,不是函数名

bash 复制代码
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 变量名=变量

bash 复制代码
#! /bin/bash

func(){
	local name=abc
	echo $name
}
func
echo $name

# 输出 abc
# 输出 空

exit命令

exit命令用来退出当前shell进程,并返回一个退出状态,使用$?可以接受这个退出状态

exit命令可以接受一个正数之作为参数,代表篇退出状态,如果不指定,默认状态值是0

exit退出状态只能是一个介于0~155之间的整数,其中只有0表示退出成功,其他值都表示失败

bash 复制代码
#! /bin/bash
if [ $# -ne 1]
then
	echo "arguments not valid" #参数是不合法的
	exit 1
else 
	echo "arguments valid"
	exit 0
fi

文件重定向

每个进程默认会打开三个文件描述符

  • stdin 标准输入,从命令行读取数据,文件描述符为0
  • stdout标准输出,向命令行输出数据,文件描述符为1
  • stderr标准错误输出,向命令行输出数据,文件描述符为2

可以用文件重定向将这三个文件重定向到其他文件中

命令 说明
command > file stdout重定向到file
command < file stdin重定向到file中
command >> file stdout以追加方式重定向到file
command n> file 将文件描述符 n 重定向到file
command n>> file 将文件描述符 n 以追加方式重定向到file
输入和输出重定向
bash 复制代码
echo -e "Hello \c" > ouput.txt
echo "World" >> output.txt

read str < output.txt
echo $str
同时重定向stdin 和 stdout

创建bash脚本

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也可以引入其他文件中的代码

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中的内容,在修改了bashrc之后,需要进行source操作,什么用?

就是执行一遍bashrc,然后更改的环境变量等内容 生效.

相关推荐
江公望20 小时前
ubuntu kylin(优麒麟)和标准ubuntu的区别浅谈
linux·服务器·ubuntu·kylin
Lynnxiaowen20 小时前
今天我们开始学习python语句和模块
linux·运维·开发语言·python·学习
生态笔记20 小时前
PPT宏代码
linux·服务器·powerpoint
mucheni20 小时前
迅为RK3588开发板Ubuntu 系统开发ubuntu终端密码登录
linux·运维·ubuntu
skywoodsky20 小时前
Ubuntu 24.04环境下的挂起转休眠
linux
小云数据库服务专线21 小时前
GaussDB 应用侧报Read timed out解决方法
linux·服务器·gaussdb
资源补给站21 小时前
服务器高效操作指南:Python 环境退出与 Linux 终端快捷键全解析
linux·服务器·python
一苓二肆21 小时前
代码加密技术
linux·windows·python·spring·eclipse
玉树临风江流儿21 小时前
Linux驱动开发实战指南-上
linux·驱动开发
木欣欣粉皮21 小时前
Ubuntu使用图片
linux·ubuntu