我想将cppclean的输出转换为类似cppcheck的xml部分,例如:
./bit_limits.cpp:25: static data 'bit_limits::max_name_length'
成为:
<error id="static data" msg="bit_limits::max_name_length">
<location file="./bit_limits.cpp" line="25"/>
</error>
我从awk开始:
测试代码:
echo "./bit_limits.cpp:25: static data 'bit_limits::max_name_length'" > test
cat test.out | awk -F ":" '{print "<error id=\""$3"\""}
{print "msg=\""}{for(i=4;i<=NF;++i)print ":"$i}{print "\">"}
{print "<location file=\""$1"\" line=\""$2"\"/>"}
{print "</error>"}'
注意:,要运行此命令,您需要将cat
命令放回到一行中-为了便于阅读,我将其打印在多行中。
说明:
我正在使用awk
并用冒号“:”定界-将行分成有用的块,然后尝试将其构造成XML:
{print "<error id=\""$3"\""}
-提取错误ID部分{print "msg=\""}{for(i=4;i<=NF;++i)print ":"$i}{print "\">"}
-提取消息(替换缺少的冒号,这是所有剩余的部分{print "<location file=\""$1"\" line=\""$2"\"/>"}
-提取文件和行,这部分很容易,因为冒号排列很好{print "</error>"}
-最终打印结束标签这很接近,但不太正确,它产生:
<error id=" static data 'bit_limits"
msg="
:
:max_name_length'
">
<location file="./bit_limits.cpp" line="25"/>
</error>
id 字段应仅为“静态数据”,而 msg 字段应为“'bit_limits :: max_name_length'”,但其他情况都可以(我现在不介意将其分成多行-尽管我希望awk每次都不打印新行。
更新 正如@charlesduffy指出的-在上下文中-我想在bash中执行此操作,因为我想将此代码嵌入到makefile(或只是普通的bash脚本)中,以实现最大的可移植性(即无需python或其他工具)。>
答案 0 :(得分:5)
使用bash和正则表达式:
x="./bit_limits.cpp:25: static data 'bit_limits::max_name_length'"
[[ $x =~ (.+):([0-9]+):\ (.+)\ \'(.+)\' ]]
declare -p BASH_REMATCH
输出:
declare -ar BASH_REMATCH='([0]="./bit_limits.cpp:25: static data '\''bit_limits::max_name_length'\''" [1]="./bit_limits.cpp" [2]="25" [3]="static data" [4]="bit_limits::max_name_length")'
BASH_REMATCH数组中的元素1到4包含搜索到的字符串。
来自man bash
:
BASH_REMATCH
:一个数组变量,其成员由=~
二进制运算符分配给[[
条件命令。索引为0的元素是字符串中与整个正则表达式匹配的部分。索引为n的元素是字符串中与第n个带括号的子表达式匹配的部分。此变量为只读。
答案 1 :(得分:1)
可能比需要的复杂得多:
awk '{
split($1, file_line, ":")
field = 2
while(substr($field, 1, 1) != "'\''") {
id = id " " $field
++field
}
id = substr(id, 2)
while(field <= NF) {
msg = msg " " $field
++field
}
msg = substr(msg, 3, length(msg) - 1)
printf("<error id=\"%s\" msg=\"%s\">\n", id, msg)
printf(" <location file=\"%s\" line=\"%s\">\n", file_line[1], file_line[2])
print "</error>"
}' test.out