Linux学习——shell
Linux
shell 语法
转义字符
\ :\后面的一个字符按照其字面意思解释
“ ”:双引号中的内容除$、`、“之外的任何字符的字面解释
‘ ’ :单引号中除 ' 以外的任何字符按其字面解释
shell变量
环境变量:标准变量,通常由管理员定义,用来保存系统必需内容
局部变量:由用户定义和控制 export 使变量变成环境变量(全局变量)
set 命令:查看当前使用的shell变量
变量赋值
shell的变量都是字符串
var1="string"
var2='string'
var3=string
#也可以使用read输入赋值
read var
read -p "please enter a number:" num
使用变量
使用$f符号
echo $var
echo ${var} // {}可以用来替换变量
- 只读变量 readonly
var1=name
readonly var1
或者 declear -r var1 - 获取字符串长度 echo $
- 获取子串 echo ${var:l:r} //获取从l到r区间的子串
- 注意,当变量名字与其他变量有重复部分,最好加上
删除变量
使用unset
unset var
删除后变量变成空字符串
特殊变量
\(# 传入的参数个数
\)* 所有参数
$@ 所有参数
\[ 当前进程id
$1-9 传入的参数
set 可以改变传入的参数
var1="one two three"
set 'echo var1'
### 注释
```shell
# 这是单行注释
:<<EOF
这是多行注释
EOF
其中EOF可以换成其他字符串,但是前后必须一样
:<<xyz
这是多行注释
xyz
```
### 数组
数组用小括号表示,元素之间用空格分开
array=(a b c d)
也可以直接用下标更改元素值
array[0]=1
${array[i]} 读取数组元素
${array[@]}读取整个数组
${array[\*]}读取整个数组
${#array[@]}获取数组长度
### 判断语句
* if else语句
```shell
if condition
then
...
elif
then
else
...
fi
```
* case 语句
```shell
case $var in
值1)
...
...
;; #两个;;相当于break
值2)
...
...
;;
*) #相当于default
...
...
;;
esac
```
* 在shell中,不能直接用=,<,>等比较整数,因为实际上这些变量是字符串,而应该使用:
* -eq : ==
* -ne : !=
* -gt : >
* -ge : >=
* -lt : <
* -le : <=
### 循环语句
* for in do done
```shell
for i in val1 val2 val3
do
thing1
thing2
done
```
也可以使用命令的输出作为循环范围
```shell
for i in `ls`
do
echo $i
done
```
也可以指定循环范围为连续的区间,用seq命令
```shell
for i int $(seq 1 10) #输出1-10
do
echo $i
done
```
或者也可以这样写
```shell
for i in {1..10} #字母也可以是{a..z}
do
echo $i
done
```
* for((..;..;..)) do done
类似于c语言的循环
```shell
for ((i=1;i<=10;i++))
do
echo $i
done
```
* while do done
```shell
while condition
do
thing1
thing2
done
```
* until do done
当条件为真时结束循环
```shell
until condition
do
thing
done
```
eg.不断循环直到用户输入yes
```shell
until [ "${word}" == "yes" ] || [ "${word}" == "YES" ]
do
read -p "Please input yes/YES to stop this program: " word
done
```
* break
break语句可以跳出当前一层循环
但是不能跳出case
case 用;;来退出
```shell
while read name #这个循环直到输入EOF,即ctrl+D时结束
do
for ((i=1;i<=10;i++))
do
case $i in
8)
break
;;
*)
echo $i
;;
esac
done
done
```
* continue
跳过此次循环
```shell
for ((i=1;i<=10;i++))
do
if [ `expr $i % 2` -eq 0 ]
then
continue
fi
echo $i
done
```
### 标准输入输出
* `read`可以用于标准输入
* `echo`用于标准输出
read 后可以加参数:
* `-p` 后面接提示信息,相当于Python中input("Please enter balabala...")
* `t` 后面接时间,规定输入的等待时间,超过了就会跳过
### 逻辑判断与test
逻辑判断的返回值为0表示真,非零表示假
* && : `expr1 && expr2`
* || : `expr1 || expr2`
* test:
* 数值判断: test 2 -lt 3
- | -eq | == |
| ---- | ---- |
| -ne | != |
| -gt | > |
| -lt | < |
| -ge | >= |
| -le | <= |
* 字符串判断:
* | -z | 是否为空 |
| ------------- | -------- |
| -n | 非空 |
| str1 == str2 | == |
| str1 ! = str2 | != |
* 文件判断
* | -e | 存在 |
| ---- | ------ |
| -f | 文件 |
| -d | 目录 |
| -r | 可读 |
| -w | 可写 |
| -x | 可执行 |
| -s | 非空 |
* \[ \] :与test等效
### exit
* `exit`命令用来退出当前shell进程,并返回一个退出状态;使用`$?`可以接收这个退出状态。
* `exit`命令可以接受一个整数值作为参数,代表退出状态。如果不指定,默认状态值是`0`。
* `exit`退出状态只能是一个介于 `0~255` 之间的整数,其中只有 `0` 表示成功,其它值都表示失败。
### 函数
#### 返回值与stdout
与c/c++中函数不同的是,shell中的函数返回时是`exit code`
其中code的取值是0-255, 0表示正常结束
函数的`exit code`值用`$?`获取
不写`return`默认返回0
```shell
[function] func_name() { # function关键字可以省略
code1
code2
return exit code
}
```
获取函数的stdout直接用$(函数名)
output=$(func)
这样函数运行之后得到的结果不会显示到标准输出设备上,而是存储到output这个变量中
#### 函数的参数
shell函数中的参数与脚本的参数一样,都是$1-9
但是$0仍然是文件名,而不是函数名
声明函数时括号内无需写参数
```shell
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) #与使用脚本的变量一样,直接在函数名字后面加上参数即可
```
#### 函数的局部变量
用local 声明一个函数的局部变量
该变量只在函数内部有效
```shell
func(){
local var="123"
echo $var
}
func
echo $var
```
输出结果为
```
123
#一行空行,表明在函数外这个局部变量不存在
```
***
## ssh
* 用于登录远程服务器
### ssh登录
格式:
```
ssh user@hostname -p 端口号(默认端口号22)
```
### 配置文件
创建文件`~/.ssh/config`
在文件中输入:
```
Host myserver1
HostName IP地址或域名
User 用户名
Host myserver2
HostName IP地址或域名
User 用户名
```
此后登录服务器可以直接用别名`myserver1`、`myserver2`
### 密钥登录 免密登录
创建密钥
`ssh-keygen`
此后,`~/.ssh/`下会多出两个文件
* `id_rsa`:私钥
* `id_rsa.pub`:公钥
若想免密登录某个远程服务器,就复制公钥中的内容,到*远程服务器 *的`/~/.ssh/authorized_keys`文件里
也可以使用如下命令一键添加公钥
```shell
ssh-copy-id myserver
```
### scp
* 用于传输文件
```shell
scp source1 source2... destination
```
将source下的文件复制到destination
复制文件夹:
```shell
scp -r 本地文件路径 myserver:PATH
```
将服务器的文件夹复制到本地当前路径
```shell
scp -r myserver:PATH . #注意这里有个"." 表示当前路径
```
## 常见命令
### cut
-f 显示指定域 -f 1-5 显示1-5域
-c 显示字符位置 -c num1-num2
-d 指定分隔符
### paste
用于链接多个文件的域
-d 指定域
### alias
alias name='指令'
将指令改个名字
### grep
显示指定文件中包含与指定样式匹配的行
-c 只显示包含匹配样式的行
-i 忽略大小写
-l 显示有匹配行的文件名
-n 输出前显示行号
-v 显示不匹配的行
-w 查指定字
grep 81$ 文件名 寻找81结尾的
或者可以写成 grep 81\>
grep "\<王" 寻找姓王的人
### tee
显示命令同时输出命令到文件
常和管道`|`一起使用
### find
## 正则表达式
* `^` 匹配输入字符串的开始位置
* `[0-9]+` \]

浙公网安备 33010602011771号