shell脚本对文本文件的切割

shell简介

shell既是脚本语言也是解释器

Shell 是一种与操作系统内核进行交互的命令行解释器,它是操作系统的一部分。它为用户提供了一个在计算机上执行命令、运行程序和管理文件系统等功能的界面。

Shell 可以是一种脚本语言解释器,也可以是一个交互式的命令行界面。在 Linux、Unix 和类似的操作系统中,Shell 最常用的是 Bash (Bourne Again SHell)。而在 Windows 环境中,常用的是 Command Prompt (cmd.exe) 和 PowerShell。

Shell 提供了丰富的内置命令和功能,以及对操作系统的底层功能的访问权限。它可以执行系统命令、管理文件和目录、处理文本数据、控制进程、进行输入输出重定向、管道操作、通配符扩展等。此外,使用 Shell 脚本编写可以自动化执行一系列命令和操作。

Shell 的主要功能如下:

  • 执行命令和程序:通过输入命令来执行系统内置命令或运行可执行文件。
  • 文件和目录管理:创建、删除、移动、复制文件和目录,以及设置文件权限等。
  • 管道和重定向:通过管道将命令的输出连接起来,将一个命令的输出作为另一个命令的输入,同时可以使用重定向将命令的输入或输出重定向到文件中。
  • 环境变量管理:设置和使用环境变量,控制程序的行为和配置。
  • 控制流和逻辑处理:可以使用条件语句、循环和函数等控制流结构来实现复杂的逻辑处理和自动化任务。

案例:对文件进行操作,使其得到想要的数据,例如某文件下的各种各样的库文件

a.txt文本文件内容如下:

./V_1_5/hbre/middleware/calib/third_party/lib/libschedule.so
./V_1_5/hbre/gcc6/lib/libisp_algo.so
./V_1_5/hbre/middleware/calib/third_party/lib/libdiaglib.so
./V_1_2/hbre/middleware/gcc6/lib/libdcbin.so
./V_1_5/hbre/middle/gcc9/libhlog.so.1.1.1
./V_1_4/hbb/communda/party/lib/recevirer.so.10.1.1
./V_1_4/hbb/communda/party/lib/recevirer.so.10.1.1
./V_1_5/hbre/middleware/calib/third_party/lib/libdiaglib.so
./V_1_5/hbre/middleware/calib/third_party/lib/libdiaglib.a
./V_1_5/hbre/middleware/calib/third_party/lib/libdiaglib.a
./V_1_2/hbre/middleware/calib/third_party/lib/libdiaglib.so
./V_1_3/hbre/middle/gcc9/libhlog.a

需求:需要对文本文件按行读取,获取每一行的数据,按每一行的最后一个/进行切割,得到两段数据分别输出到新的文件中,举例:对./V_1_5/hbre/middleware/calib/third_party/lib/libschedule.so这一行数据,按最后一个/切割,得到./V_1_5/hbre/middleware/calib/third_party/lib和libschedule.so

操作方法:

首先创建一个文本文件,命名为*.sh,复制如下shell代码

#!/bin/bash
while IFS= read -r line; do
    # 通过最后一个斜杠进行字符串切割
    result=$(echo "$line" | rev | cut -d'/' -f1 | rev)
    before=$(echo "$line" | rev | cut -d'/' -f2- | rev)
    echo "$before" >> A.txt
    echo "$result" >> B.txt
done < ./a.txt

 shell代码解释:

#!表示指定/bin/bash作为该shell脚本代码的解释器

while;do先循环后执行

IFS(internal field separator):内部字段分割器

大多系统默认以\n 换行符,        制表符和 空格作为内部的切割符号

read -r line 表示只读,-r即read的只读选项,line读取一行的变量,即IFS切割后的一行数据给了line

result=$(echo "$line" | rev | cut -d'/' -f1 | rev) 表示将读取到的一行数据进行操作之后给result变量,$line引用line的数据,echo显示line数据,|即管道,将数据给rev操作,rev是reverse逆序函数,表示将line字符串颠倒,再通过管道传递给cut处理,cut -d‘/’表示以斜杠/切割字符串,并将结果给了-f1,f1表示切割的第一段字符串,之后将结果再通过管道传递给rev再次逆序

echo "$result" >> B.txt 表示将处理后的结果重定向到B.txt文本文件中

done < ./a.txt 有两层意思,一层意思是从./a.txt即当前目录下的a.txt文本文件中获取数据,另一层意思是当a.txt文本文件数据读取完毕,文件流指针指向末尾,表示while循环结束

上面的代码输出结果(产生了两个文本文件,A.txt和B.txt):

A.txt的内容:

可见切割成功,获取到a.txt前半部分放进A.txt中

B.txt的内容:

可见切割成功,获取到a.txt文件后半部分内容输出到B.txt中

去重

仔细观察A.txt和B.txt文本文件不难发现,两个文本文件都有重复的数据

需求,编写shell程序,去除A.txt和B.txt文本文件中重复的一行数据

创建一个A.sh或B.txt,把如下代码复制到A.sh或B.sh中

#!/bin/bash
declare -A seen  # 声明一个关联数组保存已经出现过的字符串
while IFS= read -r line; do
    if [[ ! ${seen[$line]} ]]; then  # 判断字符串是否已经存在于数组中
        echo "$line" >> A1.txt  # 将不重复的字符串写入文件
        seen[$line]=1  # 将字符串添加到已出现过的数组中
    fi
done < A.txt

 A.sh代码解释:

#!表示指定/bin/bash作为该shell脚本代码的解释器

seen是一个关联数组名,declare -A表示声明一个关联数组,关联数组不以整数作为数组下标,而是以字符串作为数组下标

if[[!${seen[$line]}]]表示判断该line是否存在于seen关联数组中,如果存在则抛弃,否则条件成立

把所有的字符串放进关联数组中,然后重定向到A1.txt文本文件中,有重复的则去掉

上面的代码输出结果(分别产生了两个文本文件,A1.txt和B1.txt):

A1.txt内容:

没有重复行数据,去重成功

B1.txt内容:

没有重复行数据,去重成功

现在无缘无故又来了个需求

需求:想把A1.txt的内容合并成一个字符串,每一行数据以冒号:作为分隔符

举例:./V_1_5/hbre/middleware/calib/third_party/lib:./V_1_5/hbre/gcc6/lib

这两行合并一行,以冒号:间隔

操作方法:

创建一个end.sh,把如下代码复制到end.sh中

#!/bin/bash
merged=""
while IFS= read -r line; do
    merged="${merged}:${line}"  # 将每一行字符串追加到变量中
done < A1.txt

# 去掉开头的冒号,并将结果写入输出文件
echo "${merged:1}" > end.txt

end.sh代码解释: merged="",表示初始化变量merged,将每一行的数据合并追加到merged变量中,以:作为间隔符

"${merged:1}" 中的1表示第二个字符,即将从第二个字符开始到末尾的数据给end.txt文本文件

上面的代码输出结果(产生了end.txt文本文件)

end.txt内容:

得到一行字符串,并以:间隔,满足需求

又来了一个新需求

需求:需要对B1.txt文件继续进行切割操作,要求获取到lib开头的数据,且小数点.及其后面的数据都不要了

举例:libschedule.so 切割后得到libschedule

操作方法:

创建一个command.sh文件,将如下代码复制到command.sh中

#!/bin/bash
sed -n 's/^\(.*lib\)\([^\.]*\)\..*/\1\2/p' B1.txt > command.txt

 command.sh代码解释:

  • sed 是一个流式文本编辑器,用于从文件或标准输入中读取文本并进行处理。
  • -n 选项用于指定 sed 不要自动打印匹配行,只有经过处理的行才会被打印出来。
  • 's/^\(.*lib\)\([^\.]*\)\..*/\1\2/p' 是 sed 的编辑命令。它使用正则表达式进行模式匹配和替换,并将匹配替换后的结果打印出来。

解释正则表达式 's/^\(.*lib\)\([^\.]*\)\..*/\1\2/p'

  • s/:表示进行替换操作。
  • ^:表示匹配行的开头。
  • \(.*lib\):用括号括起来的部分表示第一个分组,匹配以 “lib” 结尾的任意字符。
  • \([^\.]*\):用括号括起来的部分表示第二个分组,匹配不包含点号的任意字符。
  • \.:表示匹配一个点号。
  • .*:表示匹配任意字符。
  • /\1\2/:表示要替换的内容,将匹配到的第一个分组 \1 和第二个分组 \2 连接起来。
  • /p:表示打印替换后的结果。

B1.txt 是要处理的输入文件,而 command.txt 是输出文件,用于保存处理结果。通过 > 运算符将 sed 命令的输出重定向到 command.txt 文件中。

上面的代码执行后的输出结果:

得到想要的结果,因为我看到了小数点后面的数据没有了。等等,似乎切割产生了重复的数据,怎么办?

哦~简单,脚本重复利用,把去重的脚本拿来对command.txt文本文件进行操作不就得到最后想要的文本文件了吗,,哈哈哈我真是小天才~

这里我再创建一个脚本文件command_end.sh,把A.sh代码内容复制过来

使用shell脚本文件command_end.sh对command.txt文本文件操作得到最好的文本文件command_end.txt

上面的代码执行后得到的输出结果:

command_end.txt内容:

仔细检查后,没有问题啦,可以提交工作了。新的需求都解决了 呢。

天下语言为一家,不管什么语言,都是为了人类社会而服务的,他们的出现方便了我们的交流,提高了我们的生产力。

每一个字符都是有意义的~

值此第39个教师节,在这里我祝愿天底下的老师们:教师节快乐a

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值