21 Shell Script文件操作
Shell Script文件操作
一、遍历文件内容
一)for方法
查看for循环帮助手册
[root@localhost ~]# help for
for: for NAME [in WORDS ... ] ; do COMMANDS; done
Execute commands for each member in a list.
The `for' loop executes a sequence of commands for each member in a
list of items. If `in WORDS ...;' is not present, then `in "$@"' is
assumed. For each element in WORDS, NAME is set to that element, and
the COMMANDS are executed.
Exit Status:
Returns the status of the last command executed.
for ((: for (( exp1; exp2; exp3 )); do COMMANDS; done
Arithmetic for loop.
Equivalent to
(( EXP1 ))
while (( EXP2 )); do
COMMANDS
(( EXP3 ))
done
EXP1, EXP2, and EXP3 are arithmetic expressions. If any expression is
omitted, it behaves as if it evaluates to 1.
Exit Status:
Returns the status of the last command executed.
创建test文件
[root@localhost ~]# vi test.txt
01 hello world
02 hello linux
03 hello every one
1.方法一
for便利循环有两种语法格式,我们先使用第一种方式
# 编写for in方式的脚本
[root@localhost ~]# vi for_in.sh
#!/bin/bash
num = 0
for line in `cat test.txt`; do
echo $line
let num++
done
# 执行结果
[root@localhost ~]# bash for_in.sh
01
hello
world
02
hello
linux
03
hello
every
one
输出显示的确是循环遍历了文件
文件中的行数据发生了切割
遍历的元素数变成了10个
因为:
在bash在对接收到的字符串进程扩展的时候出发了词的拆分的扩展
for line in`cat file.txt`;do
这行执行时:命令替换先进行,将文件内容扩展到该位置
之后,bash先处发了词的拆分根据环境变量$IFS
$IFS中默认定义[空格/制表符/换行符]三个元素来切割字符串
修改代码:
# 复制for_in
[root@localhost ~]# cp for_in.sh for_in_v2.sh
# 修改原脚本
[root@localhost ~]# vi for_in_v2.sh
#!/bin/bash
ordifs=$IFS
num=0
IFS=$'\n'
for line in `cat test.txt`; do
echo $line
let num++
done
echo "文件总行数:$num"
IFS=$oldifs
# 查看执行结果
[root@localhost ~]# bash for_in_v2.sh
01 hello world
02 hello linux
03 hello every one
文件总行数:3
2.方法二
# 编写for exp方式的脚本
[root@localhost ~]# vi for_exp.sh
#!/bin/bash
count=`wc -l test.txt | cut -d' ' -f1`
for i in `seq $count`; do
# 使用了head与tail组合模拟游标,获取最后一行
line=`head -$i test.txt | tail -1`
echo $line
done
echo "文件总行数:$count"
# 运行结果
[root@localhost ~]# bash for_exp.sh
01 hello world
02 hello linux
03 hello every one
文件总行数:3
也可以用for的另外一种方式
#
[root@localhost ~]# vi for_exp_v2.sh
#!/bin/bash
count=`wc -l test.txt | cut -d' ' -f1`
for ((i=1;i<=count;i++)); do
# 使用了head与tail组合模拟游标,获取最后一行
line=`head -$i test.txt | tail -1`
echo $line
done
echo "文件总行数:$count"
# 运行结果
[root@localhost ~]# bash for_exp_v2.sh
01 hello world
02 hello linux
03 hello every one
文件总行数:3
二)while方法
查看while循环帮助手册
[root@localhost ~]# help while
while: while COMMANDS; do COMMANDS; done
Execute commands as long as a test succeeds.
Expand and execute COMMANDS as long as the final command in the
`while' COMMANDS has an exit status of zero.
Exit Status:
Returns the status of the last command executed.
1.方法一
# 创建file文件
[root@localhost ~]# touch file.txt
# 使用while
[root@localhost ~]# vi while_read.sh
#!/bin/bash
num=0
while read line; do
echo $line
let num++
done < test.txt
echo "文件总行数:$num"
# 查看运行结果
[root@localhost ~]# bash while_read.sh
01 hello world
02 hello linux
03 hello every one
文件总行数:3
这里用到了重定向基于while开启文件输入流每次循环根据read命令的特征只取出一个换行符的内容也就是一行
[root@localhost ~]# vi while_read_v2.sh
#!/bin/bash
# 添加一个test的输入文件描述符:3
exec 3< test.txt
num=0
while read line <& 3; do
echo $line
let num++
done
echo "文件总行数:$num"
# 删除文件描述符,3
exec 3<&-
# 查看运行结果
[root@localhost ~]# bash while_read_v2.sh
01 hello world
02 hello linux
03 hello every one
文件总行数:3
2.方法二
使用管道的实现方法
[root@localhost ~]# vi while_pipe.sh
#!/bin/bash
num=0
cat test.txt | while read line; do
echo $line
let num++
done
echo "文件总行数:$num"
# 运行结果
[root@localhost ~]# bash while_pipe.sh
01 hello world
02 hello linux
03 hello every one
文件总行数:0
观察输出结果你会发现行数统计还是0
这个是因为管道的特征造成的
管道操作符两边会开启新的子shell来处理对应的命令
所以num++的操作没有修改到父shell中的num
这点在开发中一定要特别注意
注意:补充
有人一定会说对num做export
export定义的是导出而非共享
父/子进程任意一方修改导出的变量都不会对对方产生影响
二、综合案例
一)案例需求
遍历一个目录,目录下可能还有目录
读取目录下的文本文件,找到每个文件中单词使用频率最多的单词。
需求:
列出每个文件使用频率最高的单词
忽略单词的大小写
如果是数字也理解为一个单词
同时要打印出单词的最高使用次数
# 样板数据
[root@localhost ~]# tree ./
./
└── data
├── a
│ └── test2.txt
└── test1.txt
2 directories, 2 files
# 编辑test1
[root@localhost ~]# vi data/test1.txt
01 hello world
02 hello linux
03 hello every one
# 编辑test2
[root@localhost ~]# vi data/a/test2.txt
01 hello world
02 hello linux
03 hello every one
二)代码实现
1.处理单文件
第一步:
写一个脚本计算出一个文件的单词使用频率–将文本文件以一行一个单词的形式显示出来;
将单词中的大写字母转化成小写字母,即Word和word认为一个单词;
对单词进行排序;
对排序好的单词列表统计每个单词出现的次数;
# 将大写转换为小写
[root@localhost ~]# vi process_file.sh
#!/bin/bash
cat $1 | sed 's/[A-Z]/\l&/g'
# 测试
[root@localhost ~]# bash process_file.sh data/test1.txt
01 hello world
02 hello linux
03 hello every one
tr是sed命令的简化
# 使用tr代替sed命令,并将一个单词一行显示
[root@localhost ~]# vi process_file.sh
#!/bin/bash
cat $1 | tr "[A-Z]" "[a-z]" | tr -c "[a-z][0-9]" "\n"
# 测试
[root@localhost ~]# bash process_file.sh data/test1.txt
01
hello
world
02
hello
linux
03
hello
every
one
去重,并统计单词出现次数
# 去重,统计数量
[root@localhost ~]# vi process_file.sh
#!/bin/bash
cat $1 | tr "[A-Z]" "[a-z]" | tr -c "[a-z][0-9]" "\n" | sort | uniq -c
# 测试
[root@localhost ~]# bash process_file.sh data/test1.txt
1 01
1 02
1 03
1 every
3 hello
1 linux
1 one
1 world
输出结果,先按出现次数排序,次按字母排序
# 排序
[root@localhost ~]# vi process_file.sh
#!/bin/bash
cat $1 | tr "[A-Z]" "[a-z]" | tr -c "[a-z][0-9]" "\n" | sort | uniq -c | sort -k1nr -k2
# 测试
[root@localhost ~]# bash process_file.sh data/test1.txt
3 hello
1 01
1 02
1 03
1 every
1 linux
1 one
1 world
# 只显示出现次数最多的
[root@localhost ~]# vi process_file.sh
#!/bin/bash
cat $1 | tr "[A-Z]" "[a-z]" | tr -c "[a-z][0-9]" "\n" | sort | uniq -c | sort -k1nr -k2 | head -1
# 测试
[root@localhost ~]# bash process_file.sh data/test1.txt
3 hello
2.遍历目录
第二步:
遍历整个目录,分别读取每个文件。
# 递归遍历目录
[root@localhost ~]# vi process_file.sh
#!/bin/bash
# 处理文件
function read_file()
{
cat $1 | tr "[A-Z]" "[a-z]" | tr -c "[a-z][0-9]" "\n" | sort | uniq -c | sort -k1nr -k2 | head -1
}
# 遍历目录,使用递归
function read_dir()
{
# $1表示目录
for file in `ls $1`; do
# 获取文件路径
path=$1"/"$file
# 判断是否是目录
if [ -d $path ]; then
read_dir $path
else
str=`read_file $path`
count=`echo $str | awk '{print $1}'`
word=`echo $str | awk '{print $2}'`
echo "当前文件为:$path,出现次数最多的单词为:$word,出现次数为:$count"
fi
done
}
read_dir ./data
# 运行结果
[root@localhost ~]# bash process_file.sh
当前文件为:./data/a/test2.txt,出现次数最多的单词为:hello,出现次数为:3
当前文件为:./data/test1.txt,出现次数最多的单词为:hello,出现次数为:3
原文地址:https://blog.csdn.net/weixin_48089507/article/details/142983443
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!