欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Linux Shell 学习笔记(一)

程序员文章站 2022-07-03 12:07:13
...

Linux Shell 学习笔记(一)

环境: Centos 7 bash

1. Hello World

1.1 echo

终端打印命令

命令格式:

echo "String"/'String'/String

在屏幕上打印string

  • 打印!:要么不使用”“包括要打印的String,要么使用\进行转义

1.2 printf

相比于echo,printf能适应格式化输出,与C中的printf相似

命令格式:

printf "strFormat" string1 string2 ...stringn
//示例
printf "%-5s %-10s %-4s\n" no name mark
printf "%-6.4f\n" 2.1

“-5s”:

  • ‘-‘表示左对齐,默认为右对齐

  • 5代表在屏幕上显示的列数。5.0表示数字类型时,如果数字的位数不够5,则使用0填充

  • s代表要输出的数据类型

    • s:字符串类型

    • d:整数类型

    • f:浮点数类型

2.环境变量

当一个应用程序在执行时,它接受一组环境变量,可以使用env命令进行查看。对于每一个进程,其运行时的环境变量可以使用以下命令查看$PID表示进程的id

cat /proc/$PID/environ

2.1变量赋值与相等

var=value 变量赋值,如果value中存在空格,则需要使用引号

var = value 判断变量相等

var=sssss
echo $var
echo ${var}
echo var #错误
echo "we hava many ${var} m"

2.2环境变量

环境变量:未在当前进程中定义,从父进程继承而来的变量

//例如HTTP_PROXY
echo HTTP_PROXY
export HTTP_pROXY

linux提供了许多标准的环境变量,比如$PATH

echo $PATh
#输出 /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
# 各目录路径之间使用:分割。给出命令之后,linux将会在各个目录中搜索指定命令名称的可执行文件

# 添加新的路径至$PATH
#'=' 两边没有空格
export $PATH="$PATH:/fullPATH"

2.3补充内容

2.3.1获取变量值长度
var=value
len=${#var}
echo $len
2.3.2当前SHELL版本
# way 1
echo $SHELL
#way 2
echo $0
2.3.3 检查当前是否是超级用户
if [$UID -ne 0]; then
echo not a root user
else
echo "root user"
fi

3.数学运算

在bash环境中,可以利用let,(()),[]执行基本的运算,expr和bc可以进行高级运算

3.1整数运算

var1=10
var2=30

let result=var1+var2
echo result   # 40

#let支持++/--和简写模式
let var1++
let var1--
let var1+=10
let var1-=10
let var1/=2
let var1*=2

#[]命令与let相似
result=$[var1 + var2]
result=$[$var1 + var2]

#(())使用与[]相似
result=$(($var1 + 10))
result=$((var1 + 10))

# expr
result=`expr 3 + 4`
result=$(expr $var1 + 10)

3.2 bc命令 支持浮点数运算

# 命令格式
echo "4*0.15" | b`

bc命令的参数可以置于要执行的具体操作之前,使用;进行分割

#设置数值精度
echo "scale=2;3/8" | bc

#进制转换
echo "obase=2;16" | bc                  #结果 10000
echo "obase=10;ibase=2;1000" | bc       #结果 8

#计算平方/平方根
echo "sqrt(100)" | bc
echo "10^2" | bc

4. 文件描述符&&重定向

4.1 文件描述符

0       stdin       标准输入
1       stdout      标准输出
2       stderr      标准错误    

4.2 重定向

#输出重定向
echo "i am a boy" > temp.txt        #清空原文件,然后写入
echo "i am a boy" >> temp.txt       #在源文件末追加

#tee命令 将输入输出到标准输出,并且输出到指定的文件中
echo "meaningless string" > temp.txt
cat temp.txt | tee temp.back.txt | cat

#将脚本中的文本输出到文件中(下面的例子为一个shell脚本文件内容)
#!/bin/bash

cat <<EOF>log.txt
line 1
line 2
line 3
EOF
cat log.txt     #将会输出line 1\n line 2\n line 3\n

4.3 自定义文件描述符

文件打开方式有三种,只读\截断\追加

可以使用命令exec创建自定义文件描述符

  • < 将文件内容读入stdin

  • > 截断模式写入文件,原文件内容被删除

  • >> 追加模式写入文件,数据被写在文件的尾部

    exec 3<log.txt
    cat <&3
    

find妙用

#查找当前目录以及子目录下所有的txt文件,并且找出含有‘bin’的行
find ./ -name "*.txt" -exec grep "bin" {} \; 
#删除当前目录以及子目录下所有的txt文件
find ./ -name "*.txt" -exec rm {} \;

5. 数组和关联数组

5.1 普通数组

#定义
array=(1,2,3,4,5)

#输出
echo ${array[0]}
index=1
echo ${array[$index]}

#打印所有元素
echo ${array[*]}
echo ${array[@]}

5.2 关联数组

#定义
declare -A ass_array
ass_array=([index1]=var1)
ass_array[index2]=var2

#输出
##输出元素
echo ${ass_array[index]}
echo ${ass_array[*]}
echo ${ass_array[@]}
##输出索引
echo ${!ass_array[@]}

6.别名

#创建别名 命令alias
alias new_command="command sequence"
alias install="sudo apt-get install"

alies命令生效时长尾终端的未关闭的时长

如果想保存alias设置,可以将命令写入~/.bashrc

echo alias new_command >> ~/.bashrc

删除alias设置:

1.删除~/.bashrc中的对应项
2.使用unalias命令
    unalias new_command

7. 终端信息

tput stty 两个工具

7.1 使用介绍

#获取终端行数/列数
tput cols
tput lines

#当前终端名
tput longname

#光标移动
tput cup 100 100 #坐标(100,100)

7.2 运行脚本的方法

后面的内容要真正开始编写小脚本,先从如何运行脚本开始学习

7.2.1 将脚本作为sh的命令行参数进行运行
sh ./script.sh                  #假设脚本位于当前工作目录
sh /home/path/script.sh         #使用脚本的完整目录运行脚本
7.2.2 作为有执行权限的可执行文件运行
#添加执行权限
chmod a+x script.sh             # 默认脚本位于当前工作目录,否则使用脚本的完整运行目录
./script.sh                     # 运行 同样注意脚本目录

至于文件权限的知识,后文会讲到

7.3 脚本实现不输出密码

  • stty echo 允许输出到终端

  • stty -echo 禁止输出到终端

    #!/bin/sh
    #Filename: password.sh
    echo -e "enter password"
    stty -echo
    read password
    stty echo
    echo
    echo password read done
    echo what we have got : $password
    

8.时间与日期

8.1 使用介绍

#获取时间
date
#打印纪元时
#纪元时 1970/1/1/0:0:0 至今的秒数
date +%s 

8.2 循环监视脚本

循环&&判断 不必多说

tput sc存储光标位置,在循环中,恢复之前的光标位置tput rc

tput ed清除光标当前位置到行末的内容,使得旧值被清除,新值显示在旧值位置

#!/bin/sh
echo -n Count:
tput sc

count=0;
while true:
do
if [$count -lt 40]
then let cout++;
sleep 1;
tput rc
tput ed
echo -n $count
else exit 0;
fi
done

9. 脚本调试

shell脚本调试不需要任何的工具

bash -x script.sh
# 或
sh -x script.sh

-x 标识将脚本中执行过的每一行都输出到stdout

也可以只关注某一部分代码,在脚本中可以使用如下命令启用或者禁用调试打印

set -x      # 在执行时显示参数和命令
set +x      # 进制调试
set -v      # 当命令进行读取时显示输入
set +v      # 禁止打印输入

9.1 实践

#!/bin/bash
for i in {1...6}
do
set -x
echo $i
set +x
done
echo "script executed"

9.2 自定义调试信息输出格式

通过传递_DEBUG环境变量实现

#!/bin/bash
function DEBUG()
{
echo $_DEBUG && [email protected] || :
}
for i in {1..6}
do
DEBUG echo $i
done

# 代码保存为 script.sh

运行

chmod a+x script.sh
_DEBUG=on ./script.sh

便捷调试

在脚本文件首行末添加 “ -xv”

脚本将自动以调试模式运行

9.3 函数

在 9.2 中,我们已经看到了函数

9.3.1 定义函数
#1.
function funcName()
{
statements;
}

#2.
funcName()
{
statements;
}
9.3.2 函数调用
#只需使用函数名 即可调用函数
funcName;

#参数传递
funcName arg1 arg2 ;

#示例
funcName()
{
echo $1 $2;    # 输出第一二个参数
echo "[email protected]";     # 以列表形式打印所有参数
echo "$*";     # 以实体形式打印所有参数
return 0;       # 函数返回值
}

#获取函数返回值
# 函数执行后, 返回值暂时保存在$?中
funcName
echo $?

#补充 fork炸弹
:(){ :|:& };:
#函数无限递归,造成服务器内存溢出,死机=>拒绝服务攻击
#博主也没看明白,函数的实现原理orz

10.命令

10.1 向命令传递参数

#有command命令,假设-p-v是可选项, -K NO是一个可以接受数字的选项,同时该命令可以接受一个文件名作为参数
#举例执行方式
#1. 
command -p -v -k 2 file
#2.
command -pv -k 2 file
#3.
command -pvk 2 file
#4.
command file -pvk 2

10.2 命令序列输入输出

shell脚本可以将多个命令或工具一起组合起来使用。一个命令的输出可以作为下一个命令的输入,这个命令的输出又可以作为下一个命令的输入,以此类推。

10.2.1 预备知识

输入通常通过stdin或命令参数传递给命令

输出要么存在于stderr,要么存在于stdout

我们使用管道pipe来连接多个命令,管道的标识符为 “|

被管道连接的命令,我们称之为过滤器filter

10.2.2 实践
#将ls命令的返回加上行号输出到文件中
ls | cat -n > out.txt

#获取命令的返回
output=$(ls)
ouput=`ls`      # 反引用

#创建子进程
#使用()可以创建子进程
pwd
(cd ..)
pwd             #两个输出是相同的

10.3 read命令

10.3.1 不使用回车获得键盘输入

通常bash命令行在接受到键盘回车信号后,认为用户的本次输入完成。我们可以使用read命令实现

read -n 2 var
echo $var
#执行上述命令脚本,在输入两个字符后,程序马上返回先前输入的两个字符
10.3.2 read参数介绍
# 回车方式获得输入
read var            #输入之后,回车结束本次输入

# 使用不回显的方式获取输入
read -s var

# 显示提示信息
read -p "please input:" var

# 在指定时间内完成输入(时间单位:秒)
read -2 var

# 指定定界符
read -d "EOF" var
#用户输入SSEOF之后,输入完成,var的值为SS

10.4 字段分隔符与迭代器

内部字段分割符(Internal Field Seperator, IFS)是shell文本处理的重要内容之一。

shell默认使用的定界字符组存储在$ISF中

10.4.1 处理CSV(Comma Seperated Value)

#!/bin/bash
data="name,gender,address,phoneNum"
oldIFS=$IFS
IFS=,

for item in $data;
do
echo Item: $item
done    

IFS=$oldIFS

11.循环与判断

11.1 for循环

for i in list;
do
statements;
done

#上文中list
{1..50}
{a..z}
{a..Z}

11.2 while循环

while condition
do
statements;
done

# condition 是boolean值

11.3 until

until condition;
do
statements;
done

#一直执行直到condition为true

11.4 if

if condition;
then
commands;
fi

11.5 else elif

if condition1;
then
    commands;
elif condition2;
then
    commands;
else
    commands;
fi

11.6 算数比较

-gt     大于
-lt     小于
-eq     等于
-ge     大于等于
-le     小于等于

# 格式
[ $var -gt 123 ]

11.7 文件系统比较

[-f $file_var]     判断变量代表的文件或目录是否存在,存在返回真
[-x $file_var]     判断文件是否是可执行的,可执行,返回真
[-d $file_var]     变量是否代表目录
[-e $file_var]     变量代表的文件或目录是否存在
[-c $file_var]     变量是否代表字符设备文件
[-b $file_var]     变量是否代表块设备文件
[-r/w $file  ]     文件是否可读/可写

11.8 字符串比较

[[$str1 = $str2]]   字符串是否相等
[[$str1 == $str2]]   同上
[[$str1 != $str2]]   字符串是否不相等
[[$str1 > $str2]]  字符串字母序大小比较
[[ -z $str2]]      字符串是否为空
[[ -n $str2]]      字符串是否不为空

## 示例
#!/bin/bash
str1="a"
str2="b"
if [[ $str1 > $str2 ]];
then
echo "sssssss"
else
echo "mmmmmmm"
fi
相关标签: shell linux shell