【问题标题】:Insert code at the start and end of the outer nested code block only仅在外部嵌套代码块的开头和结尾插入代码
【发布时间】:2013-01-08 07:54:21
【问题描述】:

我有一些类似的代码:

void main() {
//----------
  var a;
  var b;
  var c =[];
  var c = func(3);
  if (a == b) {
    print "nested";
  }    
//----------------
}

我想选择括号之间的内部部分,这是我尝试过的:

sed -re ':l;N;$!tl;N;s!(void \w+\(\) \{)([^])*!\1 Prepend;\n\2\nappend!g' test.txt

编辑:

我试图在第一次出现 { 之后和最后一次出现 } 之前插入代码。

例子:

void main() { 
test1
//-----------------
  var a;
  var b;
  var c =[];
  var c = func(3);
  if (a == b) {
    print "nested";
  }
test2
//-----------------
}

【问题讨论】:

  • 尝试awk 并忽略包含大括号的行。

标签: regex linux sed awk


【解决方案1】:

我认为awk 是您实际上想要做的更好的解决方案:

$ awk '/{/{i++;if(i==1){print $0,"\ntest1";next}}{print}/}/{i--;if(i==1)print "test2"}' file
void main() { 
test1
//-----------------
  var a;
  var b;
  var c =[];
  var c = func(3);
  if (a == b) {
    print "nested";
  }
test2
//-----------------
}

解释:

这是带有一些解释性 cmets 的多行形式的脚本,如果您喜欢这种形式的脚本,请将其保存到文件中,例如 nestedcode 并像 awk -f nestedcode code.c 一样运行它:

BEGIN{
    #Track the nesting level 
    nestlevel=0
}
/{/ {
    #The line contained a { so increase nestlevel
    nestlevel++
    #Only add code if the nestlevel is 1
    if(nestlevel==1){
        #Print the matching line and new code on the following line
        print $0,"\ntest1"
        #Skip to next line so the next block 
        #doesn't print current line twice
        next
    }
}
{
    #Print all lines
    print
}
/}/ {
    # The line contained a } so decrease the nestlevel
    nestlevel--
    #Only print the code if the nestleve is 1
    if(nestlevel==1)
        print"test2"
}

【讨论】:

  • 我的文件中有很多函数,比如我的文件中带有 mnay 括号的函数,所以我不能只使用括号作为搜索内容
  • @user1953864 如果你真的问了你想解决的问题并从一开始就提供所有信息,这对每个人来说都会容易得多。
  • 实际上我快到了,无法在括号之间选择任何内容。但很抱歉。我认为这很容易,不想问整个事情。在 sed 中不可能吗?当我要求 sed 时,我总是很困惑,人们说使用 awk,而当我要求 awk 时,人们说使用 sed
  • @user1953864 总是提出完整的问题并显示您尝试过的内容sed 不是解决此问题的好工具。
  • @user1953864 - wrt sed vs awk:如果您在单行上进行简单替换,请使用 sed。如果您正在做其他事情,请使用 awk。如果您使用的不仅仅是“s”和“g”sed 命令,那么几乎可以肯定您使用了错误的工具来完成这项工作。
【解决方案2】:

这可能对你有用(GNU sed):

sed '/^void.*{$/!b;:a;/\n}$/bb;$!{N;ba};:b;s/\n/&test1&/;s/\(.*\n\)\(.*\n\)/\1test2\n\2/' file
  • /^void.*{$/!b 如果该行不以void 开头并以{ 结尾,则退出(这可能需要根据您自己的需要进行定制)。
  • :a;/\n}$/bb;$!{N;ba} 如果该行仅包含换行符后跟 },则分支到标签 b 否则读取下一行并循环返回标签 a
  • :b 在这里开始替换。
  • s/\n/&test1&/ 在第一个换行符之后插入第一个字符串。
  • s/\(.*\n\)\(.*\n\)/\1test2\n\2/ 在倒数第二个换行符之后插入第二个字符串。

【讨论】:

  • 我确实理解你的代码。你能逐个解释每个人在做什么吗?我是 regex 和 sed 的新手,我不明白。否则我必须提出新问题才能理解
【解决方案3】:

sed,默认情况下,在单行上运行。它可以通过使用N 命令将多行读入模式空间来对多行进行操作。

例如,以下 sed 表达式将连接文件中的连续行,它们之间有 @ 符号:

sed -e '{
N
s/\n/ @ /
}'

(来自http://www.thegeekstuff.com/2009/11/unix-sed-tutorial-multi-line-file-operation-with-6-practical-examples/ 的示例)

【讨论】:

  • 这可能会回答如何运行多行正则表达式,但这并不能回答他关于如何匹配括号之间的代码的实际问题 ({})。
  • 我正在使用 N 和多行,但我无法反向引用括号之间的内底部分。我需要附加并预先添加一些东西。你能举一些例子,我可以在括号中添加“TEST1”和“TEST2”
  • @user1953864 如果这是您需要做的,我建议您改为运行两个修改 - 首先,在带有 { 的行之后添加 TEST1,然后添加 @987654329 @ 在行前加上}
【解决方案4】:

试试这个正则表达式:

{[^]*} // [^] = any character, including newlines.

正则表达式的 JavaScript 示例:

var s = "void main() {\n//----------\nvar a;\nvar b;\nvar c =[];\nvar c = func(3);\n//----------------\n}"
console.log(s.match(/{[^]*}/g));
//"{↵//----------↵var a;↵var b;↵var c =[];↵var c = func(3);↵//----------------↵}"

(我知道这不是 JS 问题,但它可以说明正则表达式返回所需的结果。)

【讨论】:

  • 问题标记为sed,不是JavaScript。
  • @Amber:这并不意味着 JS 不能用来说明正则表达式有效。
  • 当正则表达式引擎以完全不同的方式运行时,这不是一个有用的答案。
  • 引擎可能不同,但正则表达式本身是标准化的。我确信 OP 知道如何运行正则表达式,我给了他使用的正则表达式,以及一个显示正则表达式执行他想要的操作的示例。
  • @Cerbrus 我已经编辑了问题并尝试了你的解决方案,它确实有效
猜你喜欢
  • 2020-02-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-17
  • 2017-07-30
  • 2013-10-11
  • 1970-01-01
相关资源
最近更新 更多