3

我只需要一点帮助,因为我很少接触 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"

我需要在数十万个文件中进行搜索和替换。并且“你好可以是任何东西......包括“\n\n\n”,它应该是 3 而不是 6。例如:

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

在此先感谢您的帮助...我想我需要 awk 才能做到这一点,所以我现在正在阅读有关 awk 基础知识的教程...

4

5 回答 5

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 和其他一些工具一起使用,但不是所有工具和所有 awk。

于 2013-04-01T15:26:38.303 回答
3

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

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

当然,这假设传递给的“x”append始终是字符串文字(但是,如果不是,则没有查找和替换脚本也将起作用)。

于 2013-04-01T17:02:56.420 回答
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 已经计算出来了。

使用-O2Microsoft 编译器 (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
于 2013-04-01T17:17:11.313 回答
-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/"

这似乎解决了最初的问题,但多行。

于 2013-04-01T15:02:21.967 回答
-1

是的 perl!

x='String1.append("Hello");'
echo $x | perl -pe 's/(\w*\.append\(\")(.*)(\"\);)/my($len)=length($2); $_="$1$2, ${len}$3";/e'
于 2013-04-01T15:31:23.853 回答