【发布时间】:2019-09-22 16:42:50
【问题描述】:
我想将 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 或其他工具)。
【问题讨论】:
-
请注意,一般来说,使用字符串操作工具来解析或生成结构化数据是非常糟糕的做法。使用真正的 XML 解析器;您可以从 bash(XMLStarlet,但调用 Python 函数也很容易)调用很多好的方法,即使您的数据以语义等效但文本不同的格式编写,它也将继续工作生成它的工具的下一个版本。
-
@CharlesDuffy 感谢您的建议:)。在这种情况下,我真的想把它嵌入到一个makefile中。我不希望用户只有基本的 bash、sed、awk 等任何先决条件(如 python 或其他)......它就是这样一个简单的 XML
-
我用来在一次传递中有效地将单个流读取到多个 shell 变量中的常用方法不工作(或者,更确切地说,不允许那些shell 变量作为不同的 make 变量持久化)在 makefile 的上下文中(其中每个操作由不同的 shell 实例运行),因此答案在 makefile 上下文中应该是有用的,这是要添加的重要上下文。顺便说一句,您是在分配
SHELL=bash,还是您的 shell 真的是sh(默认情况下使用 make)并且问题被错误标记? -
(旁白:就我个人而言,我使用Nix 来组装构建系统;它会为您完成组装依赖项的所有工作,因此使用 Nix 描述,而不是 Makefile,您可以拥有任何您需要的依赖项——Python 模块或整个 Python 解释器、JavaScript 编译器、应用了特定补丁的 coreutils、非常特定的 bash 版本、anything——由构建过程本身以完全可重现的方式提供) .
-
@CharlesDuffy 是的,这是真的 - 我正在使用
bash专门用于我的 makefile。我们为我们的 makefile 设置了一个很好的设置,这是对它的一个小调整,所以这就是我真的想坚持使用它的原因:)