需要SED或AWK脚本来进行strlen优化

时间:2013-04-01 14:11:35

标签: regex sed awk

我只需要一点帮助,因为我很少接触sed或awk。我正在尝试替换

String1.append("Hello");   // regexp to find this is: \w*\.append\(".*"\) 

String1.append("Hello", 5);  // note it has to figure out the length of "Hello"

我需要进行搜索并替换成千上万的文件。并且“Hello可以是任何东西......包括”\ n \ n \ n“,它应该是3而不是6.例如:

s.append("\n\n\n");  ---> s.append("\n\n\n", 3);

提前感谢您提供任何帮助......我想我需要awk这样做,所以我现在正在阅读有关awk基础知识的教程...

5 个答案:

答案 0 :(得分:5)

由于您希望在包含代码的某些文件上运行此功能,因此以下是该完整功能的示例:

$ cat file
foo() {
   String1.append("Hello");
   if (bar) {
      s.append("\n\n\n");
   }
   else {
      s.append("\n\\n\n\\\n");
   }
}
$
$ cat tst.awk
match($0,/[[:alnum:]_]+\.append\(".*"\)/) {
    split(substr($0,RSTART,RLENGTH), orig, /"/)

    head = substr($0,1,RSTART-1) orig[1]
    tail = orig[3] substr($0,RSTART+RLENGTH)

    tgt = orig[2]
    gsub(/[\\][\\]/,"X",tgt)
    gsub(/[\\]/,"",tgt)

    $0 = sprintf("%s\"%s\", %d%s", head, orig[2], length(tgt), tail)
}
{ print }
$
$ awk -f tst.awk file
foo() {
   String1.append("Hello", 5);
   if (bar) {
      s.append("\n\n\n", 3);
   }
   else {
      s.append("\n\\n\n\\\n", 6);
   }
}

我将原始发布问题中的示例中的“\ w”替换为POSIX等效“[[:alnum:] _]”以便于移植。 “\ w”将与GNU awk和其他一些工具一起使用,但不是所有工具,也不是所有工具。

答案 1 :(得分:3)

由于这是C ++,您是否考虑过使用预处理器?另外,您可以考虑使用sizeof运算符,而不是自己计算每个字符串的长度。

#define append(x) appendSize(x, sizeof(x))

当然,这假设传递给append的“x”总是一个字符串文字(但是,如果它不是那么没有找到并且替换脚本也将起作用)。

答案 2 :(得分:2)

这可能更适合作为评论,但更难以显示信息。在我看来,尝试通过修改源来优化字符串长度可能不是最好的解决方案。也许有一个很好的理由,但将它留给编译器可能是一个更好的解决方案(并且更简单)。根据编译器和选项,甚至可能不使用strlen()调用。编译器可以计算出常量字符串的长度。例如,考虑一下:

int main(int argc, char** argv)
{
   string s = argv[1];
   cout << s << endl;
   s.append( " stuff" );
   cout << s << endl;
   return 0;
}

使用-O(g++ -O file.c)编译时,汇编的相关位是:

400ad2:       ba 06 00 00 00          mov    $0x6,%edx
400ad7:       be 6c 0c 40 00          mov    $0x400c6c,%esi
400adc:       48 89 e7                mov    %rsp,%rdi
400adf:       e8 0c fe ff ff          callq  4008f0 <_ZNSs6appendEPKcm@plt>

注意第一条mov指令。已经计算出长度为6的长度。

-O2与Microsoft编译器(v16.00.40219.01)一起使用会产生类似的内容:

0000005C: 6A 06              push        6
0000005E: 68 00 00 00 00     push        offset ??_C@_06PNGALGA@?5stuff?$AA@
00000063: 8D 4C 24 0C        lea         ecx,[esp+0Ch]
00000067: E8 00 00 00 00     call        ?append@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAEAAV12@PBDI@Z

答案 3 :(得分:-1)

请有人改进这个解决方案:

x='String1.append("Hello");'
len=`echo $x | sed 's/\\//g' | sed 's/\w*\.append("\(.*\)");/\1/' | awk '{print length($0)}'`
echo $x | sed "s/\(\w*\.append(\".*\"\)\(.*\)/\1,$len\2/"

这似乎解决了原来的问题,但是多行。

答案 4 :(得分:-1)

是的perl!

x='String1.append("Hello");'
echo $x | perl -pe 's/(\w*\.append\(\")(.*)(\"\);)/my($len)=length($2); $_="$1$2, ${len}$3";/e'