使用 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<vector<double>>\& \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<vector<double>>\& \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 字段中转义<
或 >
。 (请参阅原始问题下的评论)
唯一的缺点是如果一个函数只包含一个数组(或两个以上的数组)作为参数,你可能会触发一些杂散的替换。以上是关于使用 bash 脚本和测试处理进行代码编辑的主要内容,如果未能解决你的问题,请参考以下文章
第七课-第二讲 07_02_bash脚本编程之六 使用脚本选项及组合条件测试
第七课-第二讲 07_02_bash脚本编程之六 使用脚本选项及组合条件测试
用于测试给定用户是不是可以读取目录和其中所有文件的 Bash 脚本?