sed shell 替换空格_Shell脚本在软件工程中的应用

一个大工程往往是由许多模块组成的,模块下又细分很多子模块,比如Autosar工程,分为bsw、mcal、rte等,而bsw模块下又有Com、PduR、CanIf、CanNm等等几十个子模块,而且完成一个大工程的开发往往由许多工程师一起参与,然后各自提交代码到主工程,这就引起一个潜在问题,在众多的子目录之间是否有同名的文件呢?因为许多工程师可能需要使用同一个头文件,而在他们的子工程中就可能放了多个这个头文件,这个在编译的时候可能出现不同的c文件使用了不同目录下的同名头文件,如果这些同名头文件内容不一致,这会带来很多潜在的bug。那么怎么知道这个大工程中存不存在同名而分布在不同目录下的文件呢(有的编译器对于这个问题是不会给任何提示的,比如Greenhills)。本文就来讲讲如何使用shell脚本来解决此问题,并输出这些同名文件所在的路径。

先介绍一下本文所使用的工程,第一级目录如下图所示:

86991ab91263f7384e19709273e835f0.png

各个目录下又细分许多模块,模块中可能还细分成多个子模块,不同层级目录下有各种类型的格式文件,比如: .h, .c, .hex, .dpa, .inc, .asm, .pro文件等等。

Grennhills头文件查找规则:Greenhills是一个总的gpj工程文件下,包含多个子gpj工程构成,如下图:

c4bf76b4b515a383d46ee4cbb94c3a67.png

最小子工程中有此子工程所有c文件编译时的头文件查找目录,例如bsw.gpj:

              -I..\..\Mcal\Gpt\include

              -I..\..\Mcal\Spi\include

              -I..\..\Mcal\Adc\include

              -I..\..\Davinci\Appl\Include

              -I..\..\Davinci\Appl\IncludeHw

..\..\Mcal\Crypto_TS \src\Crypto.c

..\..\Mcal\Crypto_TS \src\Crypto_ASRExtension.c

..\..\Mcal\Crypto_TS \src\Crypto_Hse.c

当编译Crypto.c时,头文件将按照”-I”指定的目录从第一个开始往下查找,直到找到所需的头文件。

        那么这种按顺序查找头文件的方法有个问题,就是如果不同的子工程所指定的头文件目录顺序不同甚至文件夹不同,而这些文件夹中很可能存在多个同名但是内容却不相同的头文件,这样会给工程带来逻辑错误。

        那我们如何确保所有文件夹中的头文件都是唯一的呢?或者说假设存在这些同名而不同目录的头文件,怎么找到它们并且将其目录列出来呢?本文将使用shell脚本寻找这些同名头文件,并将它们的目录打印到一个txt文件中。So, let’s go.

STEP 1

首先在编译工程根目录下找出所有的gpj文件并将其目录打印到gpjdir.txt

find . -type f -name "*.gpj"> gpjdir.txt

得到:              

48e4f676ca9736b421c3254bff18380a.png

STEP 2

利用每个子工程的头文件目录前面都有”-I”的特点,我们可以逐个gpj文件将这些”-I”的行提取出来,对于没有”-I”的gpj则忽略。比如bsw.gpj:

sed -n '/.*-I/p' ./src/bsw.gpj > bsw.txt

得到:

09a6ef40da543beea99bf7b0e338af70.png d99648bb3cd35147ef6f57771d80e5c2.png

…共76个目录。

为了便于使用,我们需要将”-I”及其左边的空格全部删除,且将左斜杠替换成右斜杠(linux的目录使用的是右斜杠):

删除”-I”及其左边的空格:

sed -i 's/.*-I//' bsw.txt

左斜杠替换成右斜杠:

sed -i 's/\\/\//g' bsw.txt

得到:

2fd7136a09e6792c652d0b32a9d8c0bc.png

因为这些gpj文件都在工程的3级目录下,而我们是在编译工程GHS文件夹下工作即二级目录,因此需要删除每行的一个”../”:

sed -i 's/\.\.\///' bsw.txt

       得到:

0621dcd06d862f9c81e398df9e60ec8d.png

接下来我们就可以将每个目录下的头文件及其路径全部打印到bswhfilesdir.txt中,这里将使用一个while循环:

while read linedofind $line -type f -name "*.h" >> bswhfilesdir.txtdone < bsw.txt

将得到bsw.gpj子工程的全部头文件及其目录:

7b2f7f6d02c1927c9d1b834fa73c20b5.png

…共1957个。

STEP 3

接下来就是本文的关键部分:这1957个头文件是不是有同名而不同目录的文件。

方法很多,楼主打算这么做:先去掉所有行的目录,只保留文件名。

while read linedoecho ${line##*/} >>bswhNoDirFiles.txtdone < bswhfilesdir.txt

得到(1957行,示意仅展示头几行):

eeb4233f1e529c78d3be4e514ba45d17.png

然后排序,再删除掉单个的文件而保留重复的行(只保留一行)。将使用sort+uniq组合拳一步到位:

sort -n bswhNoDirFiles.txt |uniq -d > bswrepeat.txt
86d127253cbfa5052650c57e11ba6116.png

                        …

29c426adf6bc05df1c714fc7af40f388.png

哇塞,共计147个同名而不同目录的头文件!!可以随机抽几个到bswhfilesdir.txt查找验证一下的。

STEP 4

最后将根据这些文件名,在bswhfilesdir.txt中找到它们对应的主人:

while read linedosed -n "/\/$line$/p" bswhfilesdir.txt >> bswrepeatDir.txtdone < bswrepeat.txt
423418f03f61cf69ed3d64774ffb9433.png

对于像最后示意的这一对,是同名同目录,这是因为有重复包含的原因,所以最后要删除掉这些行:

Uniq -n bswrepeatDir.txt > bswrepeatDirUniq.txt

最后用Beyond Compare对比一下:

a72814f2df24425a02c907b51862a95d.png

以上仅仅是对bsw.gpj工程的示例,读者可使用while循环等将所有子工程集中在一个脚本中进行处理。

编辑:Zhang Jinwei

往期文章:

C++面向对象编程的三个特性

嵌入式Linux学哪些东西

关于软件刷新的Utility File

c语言中的存储

DNS 报文格式简介

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值