如何在sed中替换mutiline模式空间

时间:2019-11-10 19:23:18

标签: sed

我有一个数据,如下所示在文件test.cs中

using System;
using System.Data;
using Sample.test.value;
namespace Sample.test {

  class testclass{  

    public testclass(){


    }
  }
}

我希望输出为

namespace Sample.test {
 using System;
 using System.Data;
 using value;
  class testclass{  

    public testclass(){


    }
  }
}

我只想通过使用sed来实现

我尝试使用以下sed脚本,并且能够复制并粘贴using内部名称空间

/^using/{
 H
 d
}
/^namespace/{
 G
}

但是无法在using语句中替换名称空间。在此示例中,我以“ Sample.test”命名空间为例。但实际上,它可以是任何东西。

3 个答案:

答案 0 :(得分:1)

可以使用awk。但不确定是什么触发了该动作以及它如何作用于您的真实数据。

awk '/^using/ {s=s"\n"$0;next} /^namespace/ {print $0 s;next} 1' file
namespace Sample.test {
using System;
using System.Data;
using Sample.test.value;

  class testclass{

    public testclass(){


    }
  }
}

答案 1 :(得分:1)

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

sed '/using/{s/^/ /;s/Sample\.test\.//;H;d};/namespace/{p;g;s/.//;n;/^$/d}' file

在保留空间中收集包含using的行,但首先添加一个前导空格并删除所有Sample.test.字符串。遇到namespace时,打印该行,附加保留空间,删除前导换行符,打印这些行,然后获取下一行,如果为空则将其删除。

答案 2 :(得分:1)

此sed脚本可转换您的测试数据,但是如果您的文件包含多个using / namespace块,或者空白不相同,则将需要更改。

# match using lines
/^using/{
    s/^/ /  # prepend whitespace 
    H       # append to hold
    d       # don't print (yet)
}

# match namespace lines
/^namespace/{
    G       # append the using block after namespace line

    # loop while we can strip a namespace name from a using line
    :a
    s/\(\([^ ]*\) {.*using \)\2\./\1/
    ta

    # read in next line and delete it if empty
    N
    s/\n\n/\n/g
}

# implicit print

第二个s///命令查找{之前的名称(即\([^ ]*\)),然后是带有相同名称的using行和句点(即\2\.)。由于结尾\2\. ... \1的初始集合,因此末尾\(之外的整个匹配项都可以作为\)使用,并替换了原始文本。


基于@Jotne的答案,等效的awk版本是:

/^using/ {
    # store using lines, along with a prepended space
    a[++i] = " " $0
    next
}
/^namespace/ {
    print

    # strip namespace name from using lines, then print
    r = " " $2 "[.]"
    for(i in a) {
        sub(r, " ", a[i])
        print a[i]
    }

    # delete subsequent line if it is blank
    getline
    if ($0) print

    next
}

# print every other line
1

此处的正则表达式(r)后面是空格,然后是名称空间名称(在名称空间行上应为$2)和句点。 sub()仅用一个空格替换保存的使用行的此正则表达式。