使用 bash 脚本和测试处理进行代码编辑

Posted

技术标签:

【中文标题】使用 bash 脚本和测试处理进行代码编辑【英文标题】:Code editing using bash script and test processing 【发布时间】:2019-12-20 08:54:10 【问题描述】:

我有一个文件,它定义了许多带有表单标题的方法

void Method1(double arg1[M][N], double arg2[M][N], ...)


我想使用 bash 脚本将参数 "double arg1[M][N]""double arg2[M][N]" 分别替换为 "const vector<vector<double>>& arg1""vector<vector<double>>& arg2",这样 函数头读作

void Method1(const vector<vector<double>>& arg1, const vector<vector<double>>& arg2, ...)


如何使用 awk 或 sed 来实现这一点?到目前为止,我已经尝试在这样的文件上两次调用sed

sed -i "s/double/const vector\<vector\<double\>\>\&/g" file.cpp

紧随其后

sed -i "s/\[M\]\[N\]//g" file.cpp

但对 sed 的第一次调用会匹配其中包含“double”模式的任何内容,包括只有 double 类型的标量参数的方法,这些参数必须保持不变。

【问题讨论】:

Fazlin -- 你有一个很好的方法,只是sed 's/double \(arg[0-9]\)\[M\]\[N\]/const vector&lt;vector&lt;double&gt;&gt;\&amp; \1/g' 【参考方案1】:

使用带有基本正则表达式的sed 的简短版本(当然不是那么短)可能类似于:

sed -i 's/double arg1\[M\]\[N\],[ ]double arg2\[M\]\[N\]/const vector<vector<double>>\& arg1, const vector<vector<double>>\& arg2/' yourfiles

使用/输出示例

$ echo "void Method1(double arg1[M][N], double arg2[M][N], ...)" | 
sed 's/double arg1\[M\]\[N\],[ ]double arg2\[M\]\[N\]/const vector<vector<double>>\& arg1, const vector<vector<double>>\& arg2/'
void Method1(const vector<vector<double>>& arg1, const vector<vector<double>>& arg2, ...)

您可以在 s/.../.../ 之前添加额外的 0,/double arg1\[M\]\[N\],[ ]double arg2\[M\]\[N\]/ 保护,以确保如果您需要限制为 1 次替换,则仅替换文件中的第 1 次。

编辑以添加捕获组和反向引用

根据您的评论,如果需要概括数组名称,您可以使用 \([^[]*\) 匹配和捕获名称,然后使用编号的反向引用(\1\2)重新插入名称,例如

sed 's/double \([^[]*\)\[M\]\[N\],[ ]double \([^[]*\)\[M\]\[N\]/const vector<vector<double>>\& \1, const vector<vector<double>>\& \2/'

编辑awk 解决方案的每个请求

正如评论中提到的,这个问题并不适合awk 解决方案,原因有两个:(1)函数声明不是一组分隔的字段,在 字段上很容易被破坏-分隔符; (2) awk 不提供文件内的就地替换。 (有些版本可以,否则你必须使用写入新文件并替换旧文件)

要使用awk 解决这个问题,您基本上必须系统地应用字符串操作函数来替换所需的子字符串。可行,只是不是您认为的正常首选方法。你可以这样做:

# match line with "... arg1[M][N], double arg2[M][N]"
awk -F", " '/[^[]*\[M\]\[N\],[ ][^[]*\[M\]\[N\]/ 
    gsub(/double/,"const vector<vector<double>>&")  # sub double/<vector<vector<double>>&
    gsub(/\[M\]\[N\]/,"")                           # remove [M][N]
1' files                                           # print record

上面的命令只是简单地将double 替换为 reference to vector of vector of doubles 语法,使用gsub 对整个记录进行操作。然后再次使用gsub 删除"[M][N]",以所需的形式留下记录。有很多方法可以做到这一点,这只是awk 想到的第一种第二种方法。

【讨论】:

非常感谢您的回复。您的解决方案非常适合给定的方法签名。但是,参数名称“arg1”和“arg2”仅用作示例;在文件中定义了几个具有不同参数名称的方法。有没有更通用的方式来匹配double blah[M][N] 是的,您可以使用 double \([^[]*])\[M\]\[N\], 作为 match 与捕获组 \(...\) 保留每个名称,但随后您将需要重新插入反向引用.我将删除一个编辑。 好的,它有效!我的意思是,您的带有捕获组和反向引用的通用版本:sed -i 's/double \([^[]*\)\[M\]\[N\]/const vector&lt;vector&lt;double&gt;&gt;\&amp; \1/g' file.cpp 非常感谢,因为它可以节省我在多个文件中手动编辑函数的大量时间。 我会接受这个作为答案,但是如何使用 awk 来实现呢? @unbound37 问题是,你为什么要在 awk 中实现这个? - 看起来像是 sed 的工作【参考方案2】:

你可以试试下面sed:

sed 's/double \(arg[0-9]\)\(\[[MN]\]\[[MN]\]\)/const vector\<vector\<double\>\>\& \1/g' file.cpp

上述命令在double[M][N] 之间搜索模式arg[0-9],并将其放在所需的const vector 模式之间。这可以与任意数量的参数一起使用。

我没有包含sed-i 选项,以便您在更新前进行验证。

【讨论】:

我也会投票给那个。善用全局。请注意,您不必在 replace 字段中转义 &lt;&gt;。 (请参阅原始问题下的评论) 唯一的缺点是如果一个函数只包含一个数组(或两个以上的数组)作为参数,你可能会触发一些杂散的替换。

以上是关于使用 bash 脚本和测试处理进行代码编辑的主要内容,如果未能解决你的问题,请参考以下文章

第七课-第二讲 07_02_bash脚本编程之六 使用脚本选项及组合条件测试

第七课-第二讲 07_02_bash脚本编程之六 使用脚本选项及组合条件测试

bash颜色变量数组相关脚本示例

用于测试给定用户是不是可以读取目录和其中所有文件的 Bash 脚本?

为啥C语言用execl执行bash shell脚本会出现Exec format error

在bash脚本中使用set -o来设置命令行编辑