linux的shell学习笔记

shell脚本第一行写明解释器的路径: #!/bin/bash
运行脚本两种方式:使用bash命令运行shell文件,或授予脚本文件执行权限,可直接执行文件
shell启动时,一开始执行一组命令来定义提问文本、颜色等设置,命令存放在~/.bashrc中
登录shell放在~/.bash_profile
shell历史记录文件~/.bash_history
bash中每个命令或命令序列通过使用分号或换行符来分隔

echo用于终端打印
printf 用于终端打印
env 查看所有与终端相关的环境变量
cat /proc/$PID/environ 查看进程的环境变量 (PID设置成进程的ID,总是一个整数)
pgrep 进程名 获取进程的ID

变量赋值和变量相等操作要区分
变量赋值:var=value
变量相等操作: var = value

export 用来设置环境变量
export PATH="$PATH:/home/usr/bin"
或者
PATH="$PATH:/home/usr/bin"
export PATH

常用的环境变量有: PATH HOME PWD USER UID SHELL

获取变量长度的方法: ${#var}

数学运算使用 let (()) [] 方式,高级操作时使用expr,bc

使用let时,变量名之前不需要再添加$
no1=4;
no2=5;
let result=no1+no2

let支持++自加操作 --自减操作 let no1++ let no1-- let no1+=6 let no1-=6

[]操作符 []中也可以使用$前缀
result=$[no1 + no2] result=$[$no1 + 5]

使用(())时,变量名之前需要加$
result=$((no1 + 50))

expr用于基本算数操作时,不支持浮点数,支持整数
bc也是一个计算工具

stdin为 0 stdout为1 stderr2
> 输出文本重定向或保存到一个文件中 目标文件中内容会被清空
>> 文本追加到目标文件中

将错误和输出重定向: 1>out.txt 2>err.txt
将错误和输出重定向到一个文件 2>&1 out.txt 或者 &> out.txt

查看文件内容 cat tmp.txt
$?获取命令执行的状态码 echo $?

更改文件的权限: chmod 000 a.txt 给文件增加可执行权限: chmod +x a.out


在控制台显示输出并重定向到一个文件中覆盖原来文件: cat a.txt | tee out.txt

在控制台显示输出并重定向到一个文件,在原来的文件上追加内容: cat a.txt | tee -a out.txt

使用stdin作为命令参数。只需要将-作为命令的文件名参数即可:$ cmd1 | cmd2 | cmd -

将文件重定向,作为命令输入: cmd < file

将脚本内部的文本块进行重定向:cat<<EOF>log.txt与EOF之间的内容作为stdin的部分输入到log.txt中
cat<<EOF>log.txt
LOG FILE HEADER
EOF

创建自定义文件描述符: exec 3<input.txt #使用文件描述符3打开并读取文件input.txt
创建并使用自定义文件描述符过程:[追加模式很相似]
exec 3<input.txt
cat <&3

数组的声明:array_var=(1 2 3 4) 或 array_var[0]="test1" array_var[1]="test2"
输出数组内容: ${array_var[0]} 或index=1 ${array_var[$index]}
以清单形式打印所有值: ${array_var[*]}或${array_var[@]}
打印数组的长度(个数) ${#array_var[*]}

定义一个关联数组: declare -A ass_array
添加元素的方法: ass_array=([index1]=val1 [index2]=val2) 或 ass_array[index1]=val1 ass_array[index2]=val2

使用别名 alias
alias new_command='command sequeue' 例子:alias install='sudo apt-get install'
可以将别名输入到~/.bashrc中,使别名变得长期有效 echo 'alias cmd="command seq"' >> ~/.bashrc
删除别名使用unalias命令或者 alias example= 取消example别名
创建一个别名,它能删除原始文件同时在baskup目录中保留副本: alias rm='cp $@ ~/backup && rm $@'
创建别名时,如果存在同名的,原有的别名将被新的设置取代

获得终端信息使用 tput stty

获得日期date
打印纪元时 date +%s
设定日期输出格式 使用+结合参数 date "+%d %B %Y"
设置日期 data -s "格式化的日期字符串"
计算脚本执行时长使用的逻辑: 使用执行后的纪元时减去执行前的纪元时

脚本执行的延时处理 sleep 整数

脚本调试模式: bash -x script.sh 或 sh -x script; 使用set -x set +x 在脚本中对调试区域进行限制;
使用_DEBUG环境变量设置自定义调试模式:
#!/bin/bash
function DEBUG()
{
["$_DEBUG" == "on"] && $@ || :
}
for i in {1..10}
do
DEBUG echo $i
done
使用"on"来运行上面脚本 _DEBUG=on ./script.sh
*命令:告诉shell不要进行任何操作

在脚本中使用 set builtin来启动或禁止调试打印
set -x 在执行时显示参数和命令 set +x 禁止调试 set -v 当命令进行读取时显示输入 set +v 禁止打印输入
使用shebang调试:将#!/bin/bash 改成 #!/bin/bash -xv 打开调试功能,不用其他选项。

创建函数使用:
function fname()
{
statements;
}
或者
fname()
{
statements;
}
使用函数名就可以调用某个函数 fname ;#执行函数 fname arg1 arg2 arg3

带参数的函数 fname arg1 arg2;
fname()
{
echo $1,$2;#访问参数1和参数2
echo "$@";#以列表的形式一次性获取所有参数并打印
echo "$*";#类似于$@,但是参数被作为单个实体
return 0;
}
Fork炸弹 :(){:|:&};:
导出函数 export -f fname 函数的作用于就可以扩展到子进程中
获取命令的返回值 echo $?;
检测命令是否成功结束:CMD="command"; $CMD; if [ $? -eq 0];then省略
向命令传递参数: -p -v -k 还有文件也可以作为参数 $command -p -v -k 1 file

管道操作符| 通过|可以将上一个命令的输出当做下一个命令的输入 cmd1 | cmd2 | cmd3

利用子shell生成一个独立的进程,使用()来定义一个子shell
pwd;
(cd /bin; ls);
pwd;

读取键盘或标准输入中的文本 read
从输入中读取n个字符并存入变量variable_name
read -n number_of_chars variable_name
使用无回显的方式读取密码:read -s var
显示提示信息 read -p "Enter input:" var
在特定时限内读取输入 read -t timeout var read -t 2 var #在2秒内将键入的字符串读入变量var
用特定的定界符作为输入行的结束: read -d delim_char var read -d ":" var #表示输入时遇到:表示输入结束

运行命令直至成功
repeat()
{
while true
do
$@ && return
done
}
放入shell的rc文件中:repeat(){while true; do $@ && return ;done}
在大多数现代系统中,true是作为/bin中一个二进制文件来实现的。上面代码执行会产生一个进程,速度会慢。可以使用下面方法:
repeat(){while :; do $@ && return; done}
增加延时的重复执行命令直至成功: repeat(){while :; do $@ && return; sleep 30; done}

存储定界符的环境变量是IFS, 他是当前shell环境使用的默认定界字符串。
data="name,sex,rollno,location"
oldIFS=$IFS
IFS=","
for item in $data;
do
echo Item: $item
done
IFS=$oldIFS

IFS的默认值为空白字符(换行符、制表符或者空格)

list可以是一个字符串或者一个序列 {1..50}为1到50的数字列表 {a..z}为a到z的字母表

for可以使用for in 方式之外,也可以使用for((i=0; i<10;i++))

while condition
do
commands;
done

until循环为一直循环运行直至,给定的条件为真
x=0;
until [$x -eq 9];
do
let x++; echo $x;
done

if condition;
then
commands;
fi

if condition;
then
commands;
else if condition; then
commands;
else
commands;
fi
if和else语句嵌套有更简洁的写法:
[condition] && action; #如果condition为真,则执行action;
[condition] || action; #如果condition为假,则执行action;

算数比较 条件通常被放置在封闭的中括号内。一定要注意在[或]与操作数之间有一个空格。如果没有空格,则报错
[$var -eq 0 ] #相当于$var 等于0 时,返回真
[$var -ne 0 ] #相当于$var 为非0,不等于0时,返回真
-gt 大于; -lt 小于; -ge 大于或等于; -le 小于或等于
逻辑与 -a 逻辑或 -o
[ $var -ne 0 -a $var2 -gt 2] #使用了逻辑与-a

文件系统相关的比较:
[ -f $file_var ] 如果给定的变量包含正常的文件路径或文件名,则返回真
[ -x $var ] 如果给定的变量包含的文件可执行,则返回真
[ -d $var ] 如果给定的变量包含的是目录,则返回真
[ -e $var ] 如果给定的变量包含的文件存在,则返回真
[ -c $var ] 如果给定的变量包含的是一个字符设备文件的路径,则返回真
[ -b $var ] 如果给定的变量包含的是一个块设备文件的路径,则返回真
[ -w $var ] 如果给定的变量包含的文件可写,则返回真
[ -r $var ] 如果给定的变量包含的文件可读,则返回真
[ -L $var ] 如果给定的变量包含的是一个符号链接,则返回真

字符串比较 最好使用双中括号
[[ $str1 = $str2 ]] 两个字符串相等时返回真 # =前后都有个空格,没有空格就变成了赋值操作
[[ $str1 == $str2 ]] 这是检查两个字符串是否相等的另一个写法
[[ $str1 != $str2 ]] 两个字符串不等时,返回真
[[ -z $str1 ]] #如果str1包含的是空字符串,返回真
[[ -n $str1 ]] #如果str1包含的是非空字符串,返回真
逻辑操作符 && 和 || 能够将多个条件组合起来:
if [[ -n $str1 ]] && [[ -z $str2 ]];

cat 常用于读取、显示或拼接文件
cat file1 file2 file3... 将多个文件拼接打印
从管道读取 commands | cat
将stdin和文件的内容拼接一起 echo 'Text' | cat - file.txt #-作为stdin文本的文件名
输出时忽略额外的空白行 cat -s file
显示制表符 cat -T file.py
显示行号 cat -n # -n会为空白行加上行号,如果想跳过空白行,可以使用-b

录制 script -t 2> timing.log -a output.session #将存储时序信息(timing.log)和存储命令输出信息(output.session)分别存放
scriptreplay timing.log output.session #按播放命令序列输出

find 工作方式:沿着文件层次结构向下遍历,匹配符合条件的文件,执行相应的操作
find base_path #输出当前目录和子目录下所有文件和文件夹 .表示当前目录 ..表示上层目录
find . -print 打印匹配的文件名称,以'\n'作为用于输出的文件名进行分隔
find . -print0 打印匹配的文件名称,以'\0'作为匹配的文件名之间的定界符
find 路径 -name 正则 -print ;根据文件名或正则表达式进行搜索
find 路径 -iname 正则 -print;忽略字母大小写进行搜索
多个条件可以使用OR操作
find . \( -name "*.txt" -o -name "*.pdf" \) -print #使用\(\)将命令视为一个整体
可以使用-path匹配文件路径 find /home/users -path "*/slynux/*" -print
-regex和-path参数类似,只不过-regex是基于正则表达式来匹配文件路径的。
find可以使用否定的参数!, find ! -name "*.txt" -print
find命令可以使用-maxdepth和-mindepth来限制find命令遍历的目录深度
*注意 -maxdepth和-mindepth作为find的第三参数出现,如果作为第4个或之后的参数,效率会降低
find -type 根据文件类型进行搜索,对文件进行过滤
-type d #所有目录 f #所有文件 l #符号链接 c #字符设备 b #块设备 s #套接字 p #FIFO

文件类型分为 普通文件、目录、字符设备、块设备、符号链接、硬链接、套接字以及FIFO等。
文件都有三种时间戳,访问时间 -atime 修改时间-mtime 变化时间-ctime 这些都是以天为单位计算
-amin -mmin -cmin 这些是以分计算
-表示小于 +表示大于
find . -type f -atime -7 -print #查找打印7天内访问过的所有文件
find . -type f -newer file.txt -print #查找比file.txt修改时间更近的所有文件
基于文件大小的搜索
find . -type f -size +2k #大于2kb的文件
find . -type f -size -2k #小于2kb的文件
find . -type f -size 2k #大小等于2kb的文件
除了k,还有b块(512字节) c字节 w字(2字节) k(1024字节) M(1024K字节) G(1024M字节)
-delete 可以用来删除find查找到的匹配文件 find . -type f -name "*.swp" -size -3M -delete
基于文件权限和所有权匹配 find . -type f -perm 644 -print #打印出权限为644的文件
参数user可以是用户名或UID
find . -type f -user slynux -print
find 可以借助-exec与其他命令结合使用
find . -type f -usr root -exec chown slynux {} \; {}是特殊的字符串,对于每一个匹配的文件,{}会被替换成相应的文件名。
-exec 不能直接在参数中使用多个命令,但是可以将多个命令放在脚本中达到执行多命令效果 -exec ./commands.sh {} \;

command | xargs #xargs命令把从stdin接受到的数据重新格式化,再将其作为参数提供给其他命令
将多行输入转换成单行输出 cat example.txt | xargs
将单行输入转换成多行输出 cat example.txt | xargs -n 数字
用自定义的定界符分隔参数 echo "splitXsplitXsplit" | xargs -d x #结果为 split split split
cat args.txt | xargs -I {} ./echo.sh -p {} -l #命令会被替换成 -p arg1 -l # -p arg2 -l # -p arg3 -l
xargs -0 将\0作为输入定界符 # find . -type f -name "*.txt" -print0 | xargs -0 rm -f

结合stdin,巧妙运用while语句与子shell
cat files.txt |(while read arg; do cat $arg; done) 等同于 cat files.txt | xargs -I {} cat {}

tr可以对来自标准输入的内容进行字符转换、字符删除以及重复字符压缩
tr只能通过stdin(标准输入),无法通过命令行参数来接受输入。
tr -d 字符集合 #删除字符串中字符集合中指定的字符
字符集补集 tr -c 字符集合
echo hello 1 char 1 char 2 next 4 | tr -d -c '0-9 \n' #结果是1 2 4 这里将'0-9 \n'补集中的字符全部删除
tr -s 字符结合 # 压缩字符 tr -s ' ' 压缩空白字符,将多个连续的空白字符转换成一个
tr 中可以使用的字符类
alnum 字母和数字
alpha 字母
cntrl 控制(非打印)字符
digit 数字
graph 图形字符
lower 小写字母
print 可打印字符
punct 标点符号
space 空白字符
upper 大写字母
xdigit 十六进制字符
tr使用字符类方法: tr '[:lower:]' '[:upper:]'

md5校验 md5 file1 file2 ...
md5sum -c *.md5 # 或者是md5sum -c file_sum.md5 这个会输出校验和是否匹配的消息
sha1sum SAH-1校验和算法

加密解密的命令: crypt gpg base64 md5sum sha1sum openssl

排序命令sort 提取唯一的命令uniq
对一组文件排序 sort file1.txt file2.txt -o sorted.txt
按照数字顺序排序 sort -n file.txt
按照逆序进行排序 sort -r file.txt
按照月份进行排序 sort -M months.txt
合并两个已排序过的文件 sort -m sorted1 sorted2
找出已排序文件中不重复的行 sort file1.txt file2.txt | uniq
sort -k 数字 #表示 使用文本中第几列的键来排序
sort -k 1,3 #表示按照字符中1-3返回的字符进行排序
为了使sort的输出与以\0作为终止符的xargs命令相兼容,采用下列命令 sort -z data.txt | xargs -0 #终止符\0用来保证xargs命令的使用安全
排序时忽略不必要的空白行, sort -b # -b用于忽略文件中的前导空白行

uniq 通过消除重复内容,从给定输入中找出唯一的行,它也可以用来找出输入中出现的重复行。 uniq只能作用于排过序的数据出入,因此要么是管道,要么将排过序的文件作为输入。
uniq -u #只显示唯一的行
uniq -c #统计各行在文件中出现的次数
uniq -d #找出文件中重复的行
uniq中-s指定可以跳过前n个字符,-w指定用于比较的最大字符数
uniq -z #使用\0作为定界符,而不使用空格

最适合存储临时数据的位置是/tmp(该目录中内容会在系统重启后被清空)
创建临时文件:
filename=`mktemp`
echo $filename
创建临时目录:
dirname=`mktemp -d`
echo $dirname
创建文件名,但实际上不创建文件或目录 使用-u:
tmpfile=`mktemp -u`
echo $tmpfile
根据模板创建临时文件名:
mktemp test.XXX #X 要大写,并且至少要3个X

分割文件和数据

posted @ 2018-01-27 22:25  在左手  阅读(358)  评论(0编辑  收藏  举报