2017-04-04 73 views
1

我想从表达式匹配特定模式的C++代码库中将任何'if'块复制到文本文件。这可能使用grep/awk/sed等的组合吗?从.cpp文件中提取匹配模式的'if'块

如果我有包含类似代码的文件:

//File1.cpp 
if(/*matching-expression-1*/) 
{ 
    //Code 
} 

//File2.cpp 
if(/*non-matching-expression*/) 
{ 
    if(/*matching-expression-2*/) 
    { 
     //Code 
    } 
} 

//File3.cpp 
if((/*matching-expression-3*/) 
{ 
    if(/*non-matching-expression*/) 
    { 
     //Code 
    } 
} 

我希望得到这样的结果:

//OutputFile.txt 

File1.cpp: 
if(/*matching-expression-1*/) 
{ 
    //Code 
} 

File2.cpp: 
if(/*matching-expression-2*/) 
{ 
    //Code 
} 

File3.cpp: 
if((/*matching-expression-3*/) 
{ 
    if(/*non-matching-expression*/) 
    { 
     //Code 
    } 
} 

我可以接受包含//Code块其他匹配/不匹配if块,即使这会导致重复输入,也无需保留制表符缩进。

我没有使用grep来匹配我想要的表达式,但只给了我包含'if'块的开始的行(这是一个好的开始!),但我不确定如何继续。

任何帮助都将不胜感激!

+0

如果不匹配是在匹配的'if'内?这仅仅是“// Code”吗? –

+0

通过提取你的意思是你想从你的C++代码中删除匹配? – Markus

+0

@JamesBrown是的,在这种情况下,我只是认为它是“代码”,真的,我只是想在开始和结束括号之间找到任何东西 – AMackie

回答

1

在awk中:

$ awk '/\*matching-expression/{f=1}f{c+=sub(/{/,"{");if(sub(/}/,"}") && --c==0)f=0;print $0}' file 
if(/*matching-expression-1*/) 
{ 
    //Code 
} 
    if(/*matching-expression-2*/) 
    { 
     //Code 
    } 
if((/*matching-expression-3*/) 
{ 
    if(/*non-matching-expression*/) 
    { 
     //Code 
    } 
} 

解释:

/\*matching-expression/ { f=1 } # flag up at match 
f {        # when flag is up 
    c+=sub(/{/,"{")    # { increments counter 
    if(sub(/}/,"}") && --c==0) # if count is about be 0 
     f=0      # flag down 
    print $0      # print when flag is up 
} 

它希望每个{}都在自己的线路。那么可以有其他的东西,但只有一个{}。哦,是的@ 123的没有任何流浪的支架也适用于这里,这将需要解析括号括起来,我假设。我可能仍然可行,我会重新审视。

+0

你能解释一下吗? –

+0

这不会工作,你永远不会减少C(好吧,只有它是1,它不会用于嵌入ifs)。任何嵌入的if都会导致它将文件的其余部分写出。 – 123

+0

@ 123你可能是对的,先生。 –

-2

看看this answer,它可能会帮助你。

例如(不使用Perl的正则表达式):

grep -zo "if\\s*(condition)\\s*{[^}]*}" File1.cpp 
+0

我不认为这是答案! –

+0

好吧,我看到这个问题,它没有捕获嵌套块。 – Markus

+0

我认为这是挑战:) –

2

假设所有代码的格式相同,你的问题,有没有遗漏括号(比如在串或东西),那么这应该工作

perl -ne 'if(/if\(STRING\)/){$_.=<>;$b+=/{/g;}if($b > 0){print;$b+=/{/g;$b-=/}/g}' file 

用任何想要搜索的字符串替换字符串。

+0

这样做了!不熟悉Perl,所以我必须正确解析这个,但我想我知道它在做什么。我怀疑我必须跟踪每个{和},直到找到右大括号。有没有一种简单的方法可以在每个匹配'if'表达式开始时打印一次文件名? – AMackie

+0

@AMackie是的,它基本上只是在计数器中增加或减少一个括号,如果计数器大于0则打印。是否将'print'改为'print'$ ARGV:$ _“'做你想做的事情? – 123

+0

是的工作! – AMackie

0

有了一个for循环和sed以下将工作:

for var in $(ls *.cpp);do echo -e $var":";sed -n '/\*matching-expression/,/}/p' $var;echo -e "\n";done > outputfile 

这就需要每一个文件,然后添加一个“:”到文件名,然后用SED,显示代码从节将匹配表达式输出到输出文件中。

与此唯一的问题是,这可能会错过关闭结束花括号

为了克服这一点,你可以添加:

left=$(cat outputfile | grep "{" | wc -l) 
right=$(cat outputfile | grep "}" | wc -l) 
diff=$(echo $(($left-$right))) 
varb="";for ((i=0;i<$diff;i++));do varb=$varb"}";done 
echo $varb >> outputfile 

在这里,我们计算左大括号括号的数量和将它放置在变量left中,计算右括号括号的数目并将其放在右边,然后最后在变量diff中放置两个差异diff 然后使用此diff变量形成一个变量(varb)大括号括号。该变量最终被添加到输出文件以完成必要的语法。