《linux Shell 脚本攻略》进阶学习(第一部分)

简介:

第二章命令之乐
cat 不仅可以读取文件并且连接数据,它还能从标准输入中进行读取
要从标准输入中读取,就要使用管道操作符 
echo 'Text through stdin' | cat - file.txt。这里的-被作为来之stdin 文本的文件名称

实例 在file.txt 中写入dfagfmirgjriogjrogijdfgio后
$ echo 'Text through stdin' | cat - file.txt
Text through stdin
dfagfmirgjriogjrogijdfgio
$ echo 'Text through stdin' | cat < file.txt
dfagfmirgjriogjrogijdfgio
$ echo 'Text through stdin' | cat  file.txt
dfagfmirgjriogjrogijdfgio


cat补充内容
 -s, --squeeze-blank #压缩连续的空白行
             suppress repeated empty output lines

tr
 -s, --squeeze-repeats#将多个连续的字符压缩成单个字符
             replace each input sequence of a repeated  character  that  is
             listed in SET1 with a single occurrence of that character

如:file.txt 内容
line

line

line

line

line

line

line

line



$ cat file.txt | tr -s '\n'
line
line
line
line
line
line
line
line


cat -n stream
      -n, --number #给内容之前加上行号
             number all output lines

录制与回放终端回话,很实用

开始录制回话
$ script -t 2>time.log -a output.session
Script started, file is output.session
type commend
.....
exit

两个配置文件被同时当做script命令的参数。其中一个文件(timing.log)用于存储时序信息,描述每一个命令在何时运行,另一个文件(output.session)用于存储命令输出,-t选项用于将时序数据导入stderr。2>则用于将stderr重定向到timeing.log。
$ scriptreplay time.log output.session 


find文件查找
-print 文件跟文件夹会以\n分隔
find sourcedOf -iname "example" -print(忽略字母大小写)
匹配多个
find \( -name "*".txt -o -name  "*.pdf" \) -print

否定参数 !
find . ! -name "*.txt" -print 不以.txt 结尾的

-exec 结合多个命令
-exec ./command.sh {} \;
-exec printf "text file: %s\n" {} \;


$ find . -exec printf "text file is: %s\n" {} \;
text file is: .
text file is: ./file.txt
text file is: ./time.log
text file is: ./output.session


玩转xargs
xargs 也可以将单行或多行文本输入转换成其他格式,例如单行变多行或是多行变单行
bash黑客都喜欢单行命令

command | xargs
xargs 是一种替换方式,类似与find命令的-exec参数
实战演练
1.将多行输入装换成单行输出
cat file.txt | xargs 
line line line line line line line line
2.将单行输入装换成多行输出
指定每行最大值 -n max,每行max个参数,每个参数都是由" " 空格隔开的字符串。空格是默认的定界符
cat file.txt | xargs -n 3
line line line
line line line
line line
更多xargs使用baidu 

使用tr进行转换
tr 可以进行替换,删除,压缩
tr 只能通过stdin,而无法通过命令行参数来接受输入。他的调用格式如下
tr [options] set1 set2
echo "Hello who IS ThIs" | tr 'A-M,n-z' 'a-m,N-Z'
hellO WhO iS ThiS

使用tr删除字符
tr -d 'set1' #只使用set1 ,而不使用set2
echo "hello 0980world" | tr -d '0-9'
hello world
字符集的补集
tr -c [set1] [set2] 
 -c, -C, --complement 补数
             use the complement of SET1
zhangjianlin@zhangjianlin:~/mytest/linuxtest/linuxshellscrill/second$ echo -e  "hello 0980world" | tr -d -c '0-9 \n'
0980
zhangjianlin@zhangjianlin:~/mytest/linuxtest/linuxshellscrill/second$ echo -e  "hello 0980world" | tr -d -c '0-9'

算数运算
echo {1..50} | echo $[ $( tr ' ' '+' ) 0 ] 
1725
$[ operation ] 执行算术运算
相当于$[ 1+...+50+0 ]

文件名的处理
$name ${name%$1}$2  #${name%\.*} "%"号除去后缀名,只取文件名
${file_name#*.} 只留扩展名或后缀

校验和核实
校验对与编写备份脚本或系统维护脚本来说都非常重要
最知名且最为广泛的校验和技术是md5sum和shalsum
实战演练
计算md5sum,使用下面命令
md5sum filename 
$ md5sum file.txt 
221950d53cb7cc10da1c3e7e7ec4e0d5  file.txt
$ md5sum file.txt > file.md5
$ md5sum -c file.md5 
file.txt: 确定
sha1sum 跟 md5sum类似
对目录进行校验
校验和是从文件中计算得来的。对目录计算校验和意味着我们需要对目录中的所有文件以递归的方式进行计算
它可以使用命令md5deep或sha1deep来实现

md5deep -rl directory_path >directory.md5
#-r 使用递归的方式
#-l 使用相对路径。默认md5会输出文件的绝对路径 
用下面命令进行核实
$ md5sum -c directory.md5

批量重命名和移动批量重命名文件名称(包括后缀名)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#a!/bin/bash
functionlistfiles(){
forfilein*;  # * is all of pwd'files
do
echo $ file
done
}
functioninputRule(){
read -p  "please input the fromsuffix as *.txt:" fromsuffix;
read -p  "please input the tosuffix as .txt:" tosuffix;
read -p  "please input the part of file name:" headname;
}
functionchangename(){
count=1;
forfromname  in $fromsuffix;
do
new= "${headname}${count}${tosuffix}"
mv "$fromname" "$new" 2>  /dev/null ;
if [ $? -eq0 ];
then
echo "Renameing $fromname to $new" ;
letcount++
fi
done
}
inputRule;
changename;
#listfiles;


批量更改名称后缀,不包含名称

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/bin/bash
functioninputDialog(){
read -p  "input fromsuffix:" fromsuffix
read -p  "input tosuffix:" tosuffix
}
functionchangeSuffix(){
forfromname  in *${fromsuffix};
do
#echo $fromname \n
#echo ${fromname%$fromsuffix}$tosuffix
mv "$fromname" "${fromname%$fromsuffix}$tosuffix" #不加""mv: 目标"*.png" 不是目录
if [ $? -eq0 ];
then
echo "$fromname" rename to  "${fromname%$fromsuffix}$tosuffix"
fi
done
}
inputDialog;
changeSuffix;



echo -e "\e[1;42m Green Background \e[0m"  彩色背景打印

echo $var 或 echo ${var}

var=value 一个赋值
var = value 一个相等操作

赋值时双引号的使用(value是否包含空格)
若无空格,特殊字符,加不加无所谓
如:var=value 或 var="value"

但var="value cat" 必须加""

length=${#var}获取变量值的长度
如:
zhangjianlin@zhangjianlin:~$ echo ${#PATH}
288

算数运算
zhangjianlin@zhangjianlin:~/mytest/linuxtest/linuxshell$ echo "4 * 0.56" | bc
2.24


数组
array_var=(1212 1233 424 565)
#!/bin/bash

array_var=(1212 3434 546 7687)
echo ${array_var[*]} {}命令块,能执行命令,处理特殊字符
echo ${#array_var[*]} #4

1
2
3
4
#!/bin/bash
array_var=(1212 3434 546 7687)
echo  ${array_var[*]}
echo  ${ #array_var[*]}


alias rmback='cp $@ ~/backup; rm $@' 删除时备份


终端工具
tput和stty是两款终端处理工具
tput cols,lines,longname,cpu 100 100,

输入密码时,不能让输入的内容显示出来。用stty

1
2
3
4
5
6
7
8
9
10
#!/bin/bash
#Filename:password.sh
function  enterpassword(){
echo  -e  "Enter password"
stty - echo
read  password
stty  echo
echo  password  read
}
enterpassword


在脚本中生成延时

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/bin/bash
#Filename: sleep.sh
function  delaytime(){
echo  -n Count:
tput sc  #store cursor
count=0;
while  true ;
do
if  [ $count -lt 40 ];
then  let  count++;
sleep  1;
tput rc  #recover cursor
tput ed  #clear the content from the head to tail of cursor
echo  -n $count;
else  exit  0;
fi
done
}
delaytime;


递归函数
bash同样支持递归函数

F(){echo $1;F hello;sleep 1;}
Fork炸弹":(){ :|:& };:"这个递归能调用自身,不断产生新的进程 :勿用

利用子shell 生成一个独立进程
#!/bin/bash

pwd
(cd /bin; ls);
pwd

通过引用子shell的方式保留空格和换行符
假设我们使用子shell或反引号的方法将命令的输出读入一个变量中,可以将它放入双引号中,以保留空格和换行符(\n)
out="$(cat text.txt)" 保留空格跟换行符号
out=$(cat text.txt)


用不回显的方式读取密码read
read -s var
在特定时限内读取输入
read -t 2 var
read -t 2 -s var


使用定界符结束输入,不使用Enter结束输入
read -d ":" var  达到能输入换行的母的
zhangjianlin@zhangjianlin:~/mytest/linuxtest/linuxshellscrill/first$ read -d ":" var
dfdufdif
fdfidjf
gfgig
:

考虑CSV的数据情况

1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/bash
function  changeIFS(){
oldIFS=$IFS  #IFS的默认值是空白字符(换行符,制表符或者空格)
IFS=,
for  item  in  $data;
do
echo  item: $item
done
IFS=$oldIFS
}
data= "name,sex,rollno,location"  #使用IFS读取变量的每一个条目
     changeIFS;


#IFS默认空格这里把他变成","
输出结果
item: name
item: sex
item: rollno
item: location

实战演练

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/bash/bin
#user of shell
function  usesh(){
oldIFS=$IFS;
IFS= ":" ;
count=0;
for  item  in  $line;
do
[ $count - eq  0 ] && user=$item;
[ $count - eq  6 ] && shell=$item;
let  count++;
done
IFS=$oldIFS
}
line= "root:x:0:0:root:root:/bin/bash"
usesh;
echo  $user\'s shell is $shell



for循环
for var in list
do
conmend
done
echo {1..30};echo {a..z};echo {A..Z};echo {a..h};
for i in {a..z};
do
commend
done

for((i=0;i<10;i++))
{
commend
}

比较与测试

逻辑运算将它变得简洁
[ condition ] && action; 如果是真执行action
[ condition ] || action; 如果是假真执行action

算术比较(数字比较)
[ $var -eq 0 ] or [ $var -ne 0 ]
其他的操作符
-gt 大于
-lt 小于
-ge 大于或等于
le 小于或等于
-eq 等于

文件相关的测试
[ -f $file_var ] 是否是文件
-x 可执行
-d 目录
-e存在
-c 字符设备路径
-b 块设备
-w 文件可写
-r 文件是否可读
-L 符号连接


判断输入的是否为文件或文件夹


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/bin/bash
functionfileordir(){
if [ -e $fpath ]; then # exist
if [ -d $fpath ] ; then #directory
echo $fpath is a  dir ;
exit
fi
if [ -f $fpath ] ; then
echo $fpath is a  file ;
exit
fi
elseecho-e  "$fpath not exit" ; exit ;
fi
echo "unknow file type"
}
fpath=$1
fileordir;

zhangjianlin@zhangjianlin:~/mytest/linuxtest/linuxshellscrill/first$ bash filetest.sh .



字符串比较
使用字符串比较时,最好用双括号,因为有时候采用单引号会产生错误,所以最好避开他们。

[[ $str1 == $str2 ]]
[[ $str1 != $str2 ]]
[[ $str1 > $str2 ]]
[[ $str1 < $str2 ]]
[[ $str1 -z $str2 ]] 空字窜
[[ $str1 -n $str2 ]] 非空字窜
if [[ $str1 < $str2 ]] && [[ $str1 == $str2 ]]

test命令执行条件检测
test有助于避免使用过多的括号
之前的[]测试条件同样可以用于test命令
if [ $var -eq 0 ];then echo "True";fi
if test $var -eq 0 ;then echo "True";fi


第二章命令之乐
cat 不仅可以读取文件并且连接数据,它还能从标准输入中进行读取
要从标准输入中读取,就要使用管道操作符 
echo 'Text through stdin' | cat - file.txt。这里的-被作为来之stdin 文本的文件名称

实例 在file.txt 中写入dfagfmirgjriogjrogijdfgio后
$ echo 'Text through stdin' | cat - file.txt
Text through stdin
dfagfmirgjriogjrogijdfgio
$ echo 'Text through stdin' | cat < file.txt
dfagfmirgjriogjrogijdfgio
$ echo 'Text through stdin' | cat  file.txt
dfagfmirgjriogjrogijdfgio


cat补充内容
 -s, --squeeze-blank #压缩连续的空白行
             suppress repeated empty output lines

tr
 -s, --squeeze-repeats#将多个连续的字符压缩成单个字符
             replace each input sequence of a repeated  character  that  is
             listed in SET1 with a single occurrence of that character

如:file.txt 内容
line

line

line

line

line

line

line

line



$ cat file.txt | tr -s '\n'
line
line
line
line
line
line
line
line


cat -n stream
      -n, --number #给内容之前加上行号
             number all output lines

录制与回放终端回话,很实用

开始录制回话
$ script -t 2>time.log -a output.session
Script started, file is output.session
type commend
.....
exit

两个配置文件被同时当做script命令的参数。其中一个文件(timing.log)用于存储时序信息,描述每一个命令在何时运行,另一个文件(output.session)用于存储命令输出,-t选项用于将时序数据导入stderr。2>则用于将stderr重定向到timeing.log。
$ scriptreplay time.log output.session 


find文件查找
-print 文件跟文件夹会以\n分隔
find sourcedOf -iname "example" -print(忽略字母大小写)
匹配多个
find \( -name "*".txt -o -name  "*.pdf" \) -print

否定参数 !
find . ! -name "*.txt" -print 不以.txt 结尾的

-exec 结合多个命令
-exec ./command.sh {} \;
-exec printf "text file: %s\n" {} \;


$ find . -exec printf "text file is: %s\n" {} \;
text file is: .
text file is: ./file.txt
text file is: ./time.log
text file is: ./output.session


玩转xargs
xargs 也可以将单行或多行文本输入转换成其他格式,例如单行变多行或是多行变单行
bash黑客都喜欢单行命令

command | xargs
xargs 是一种替换方式,类似与find命令的-exec参数
实战演练
1.将多行输入装换成单行输出
cat file.txt | xargs 
line line line line line line line line
2.将单行输入装换成多行输出
指定每行最大值 -n max,每行max个参数,每个参数都是由" " 空格隔开的字符串。空格是默认的定界符
cat file.txt | xargs -n 3
line line line
line line line
line line
更多xargs使用baidu 

使用tr进行转换
tr 可以进行替换,删除,压缩
tr 只能通过stdin,而无法通过命令行参数来接受输入。他的调用格式如下
tr [options] set1 set2
echo "Hello who IS ThIs" | tr 'A-M,n-z' 'a-m,N-Z'
hellO WhO iS ThiS

使用tr删除字符
tr -d 'set1' #只使用set1 ,而不使用set2
echo "hello 0980world" | tr -d '0-9'
hello world
字符集的补集
tr -c [set1] [set2] 
 -c, -C, --complement 补数
             use the complement of SET1
zhangjianlin@zhangjianlin:~/mytest/linuxtest/linuxshellscrill/second$ echo -e  "hello 0980world" | tr -d -c '0-9 \n'
0980
zhangjianlin@zhangjianlin:~/mytest/linuxtest/linuxshellscrill/second$ echo -e  "hello 0980world" | tr -d -c '0-9'

算数运算
echo {1..50} | echo $[ $( tr ' ' '+' ) 0 ] 
1725
$[ operation ] 执行算术运算
相当于$[ 1+...+50+0 ]

文件名的处理
$name ${name%$1}$2  #${name%\.*} "%"号除去后缀名,只取文件名
${file_name#*.} 只留扩展名或后缀

校验和核实
校验对与编写备份脚本或系统维护脚本来说都非常重要
最知名且最为广泛的校验和技术是md5sum和shalsum
实战演练
计算md5sum,使用下面命令
md5sum filename 
$ md5sum file.txt 
221950d53cb7cc10da1c3e7e7ec4e0d5  file.txt
$ md5sum file.txt > file.md5
$ md5sum -c file.md5 
file.txt: 确定
sha1sum 跟 md5sum类似
对目录进行校验
校验和是从文件中计算得来的。对目录计算校验和意味着我们需要对目录中的所有文件以递归的方式进行计算
它可以使用命令md5deep或sha1deep来实现

md5deep -rl directory_path >directory.md5
#-r 使用递归的方式
#-l 使用相对路径。默认md5会输出文件的绝对路径 
用下面命令进行核实
$ md5sum -c directory.md5

批量重命名和移动批量重命名文件名称(包括后缀名)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#a!/bin/bash
functionlistfiles(){
forfilein*;  # * is all of pwd'files
do
echo $ file
done
}
functioninputRule(){
read -p  "please input the fromsuffix as *.txt:" fromsuffix;
read -p  "please input the tosuffix as .txt:" tosuffix;
read -p  "please input the part of file name:" headname;
}
functionchangename(){
count=1;
forfromname  in $fromsuffix;
do
new= "${headname}${count}${tosuffix}"
mv "$fromname" "$new" 2>  /dev/null ;
if [ $? -eq0 ];
then
echo "Renameing $fromname to $new" ;
letcount++
fi
done
}
inputRule;
changename;
#listfiles;


批量更改名称后缀,不包含名称

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/bin/bash
functioninputDialog(){
read -p  "input fromsuffix:" fromsuffix
read -p  "input tosuffix:" tosuffix
}
functionchangeSuffix(){
forfromname  in *${fromsuffix};
do
#echo $fromname \n
#echo ${fromname%$fromsuffix}$tosuffix
mv "$fromname" "${fromname%$fromsuffix}$tosuffix" #不加""mv: 目标"*.png" 不是目录
if [ $? -eq0 ];
then
echo "$fromname" rename to  "${fromname%$fromsuffix}$tosuffix"
fi
done
}
inputDialog;
changeSuffix;


本文转自lilin9105 51CTO博客,原文链接:http://blog.51cto.com/7071976/1251283,如需转载请自行联系原作者


相关文章
|
17天前
|
Shell Linux
【linux】Shell脚本中basename和dirname的详细用法教程
本文详细介绍了Linux Shell脚本中 `basename`和 `dirname`命令的用法,包括去除路径信息、去除后缀、批量处理文件名和路径等。同时,通过文件备份和日志文件分离的实践应用,展示了这两个命令在实际脚本中的应用场景。希望本文能帮助您更好地理解和应用 `basename`和 `dirname`命令,提高Shell脚本编写的效率和灵活性。
79 32
|
27天前
|
存储 Linux 网络安全
linux应急响应检查脚本
通过这个脚本,可以快速收集系统的关键信息,有助于在发生问题时进行及时的应急响应和分析。
84 34
|
2天前
|
JavaScript Shell C#
多种脚本批量下载 Docker 镜像:Shell、PowerShell、Node.js 和 C#
本项目提供多种脚本(Shell、PowerShell、Node.js 和 C#)用于批量下载 Docker 镜像。配置文件 `docker-images.txt` 列出需要下载的镜像及其标签。各脚本首先检查 Docker 是否安装,接着读取配置文件并逐行处理,跳过空行和注释行,提取镜像名称和标签,调用 `docker pull` 命令下载镜像,并输出下载结果。使用时需创建配置文件并运行相应脚本。C# 版本需安装 .NET 8 runtime。
33 1
|
5月前
|
Shell
一个用于添加/删除定时任务的shell脚本
一个用于添加/删除定时任务的shell脚本
155 1
|
3月前
|
消息中间件 Java Kafka
【手把手教你Linux环境下快速搭建Kafka集群】内含脚本分发教程,实现一键部署多个Kafka节点
本文介绍了Kafka集群的搭建过程,涵盖从虚拟机安装到集群测试的详细步骤。首先规划了集群架构,包括三台Kafka Broker节点,并说明了分布式环境下的服务进程配置。接着,通过VMware导入模板机并克隆出三台虚拟机(kafka-broker1、kafka-broker2、kafka-broker3),分别设置IP地址和主机名。随后,依次安装JDK、ZooKeeper和Kafka,并配置相应的环境变量与启动脚本,确保各组件能正常运行。最后,通过编写启停脚本简化集群的操作流程,并对集群进行测试,验证其功能完整性。整个过程强调了自动化脚本的应用,提高了部署效率。
【手把手教你Linux环境下快速搭建Kafka集群】内含脚本分发教程,实现一键部署多个Kafka节点
|
4月前
|
Shell Linux 测试技术
6种方法打造出色的Shell脚本
6种方法打造出色的Shell脚本
116 2
6种方法打造出色的Shell脚本
|
4月前
|
存储 Shell Linux
Linux 如何更改默认 Shell
Linux 如何更改默认 Shell
110 0
Linux 如何更改默认 Shell
|
4月前
|
XML JSON 监控
Shell脚本要点和难点以及具体应用和优缺点介绍
Shell脚本在系统管理和自动化任务中扮演着重要角色。尽管存在调试困难、可读性差等问题,但其简洁高效、易于学习和强大的功能使其在许多场景中不可或缺。通过掌握Shell脚本的基本语法、常用命令和函数,并了解其优缺点,开发者可以编写出高效的脚本来完成各种任务,提高工作效率。希望本文能为您在Shell脚本编写和应用中提供有价值的参考和指导。
147 1
|
4月前
|
Ubuntu Shell 开发工具
ubuntu/debian shell 脚本自动配置 gitea git 仓库
这是一个自动配置 Gitea Git 仓库的 Shell 脚本,支持 Ubuntu 20+ 和 Debian 12+ 系统。脚本会创建必要的目录、下载并安装 Gitea,创建 Gitea 用户和服务,确保 Gitea 在系统启动时自动运行。用户可以选择从官方或小绿叶技术博客下载安装包。
144 2
|
5月前
|
Web App开发 网络协议 Linux
linux命令总结(centos):shell常用命令汇总,平时用不到,用到就懵逼忘了,于是专门写了这篇论文,【便持续更新】
这篇文章是关于Linux命令的总结,涵盖了从基础操作到网络配置等多个方面的命令及其使用方法。
115 1
linux命令总结(centos):shell常用命令汇总,平时用不到,用到就懵逼忘了,于是专门写了这篇论文,【便持续更新】