Sed 命令将忽略任何带注释的匹配项

Sed 命令将忽略任何带注释的匹配项

我正在尝试使用正则表达式创建一个 sed 命令,以便仅在文本文件中没有注释的情况下替换它,但由于我对 sed 命令几乎不了解,我遇到了一些麻烦。

我找到了问题的一小部分的解决方案,但有些还不够完整,或者我无法将它们放在一起。TL;DR 版本在最后可用。

首先我们要确定我的最终目标

我想匹配文本文件中的任何内容(例如任何常规正则表达式(呵呵))不是评论道。由于我想针对多种语言进行此操作,因此我们只采用常见的 C 注释。

因此,在这种情况下,可以用不同的方式注释单词或行。我们只能//评论接下来的内容,并且我们还有/* */评论块。


环境

我目前正在使用 Mac OSX,它只支持 POSIX sed,但我安装了一个我发现更好的 GNU-sed。 (感谢Homebrew。包是gnu-sed,命令是gsed。)因此,如果您更喜欢使用其中之一,我都可以使用它们。

我在假设使用 GNU-sed 的情况下写这篇文章。


忽略一个案例

第一个问题,如何忽略某些情况。我发现很容易在这个话题

现在,这//部分对我来说似乎很容易做到,我只需要添加一个或者 (|条件将其与其他条件结合起来。

它看起来像这样:

    sed -E "/\/\/.*/! s/foo/bar/" file

那么,如果输入文件是:

foo
42
test
//foo
//42
//    foo
//something foo
foo
42
something foo
  foo

输出是:

bar
42
test
//foo
//42
//    foo
//something foo
bar
42
something bar
  bar

所以现在,我只想把我的反思集中在/* */评论区。


通过多行匹配

第二个问题,如何使正则表达式通过多行进行匹配。嗯,我认为这是主要问题。我发现这个话题讨论如何仅通过一个换行符进行匹配。嗯,我花了一点时间才明白它是如何工作的。但这部分解决方案给我带来了新的问题和新的疑问。

显然它只能忽略一个新行( \n)。所以我现在想要做同样的事情,但是对于未知数量的行(从 0 到无限 ( *))。我打赌我必须循环遍历这些行,但这就是我陷入困境的地方,因为我对 sed 的命令一无所知,这对我来说真的很尴尬。

在我的搜索过程中,我发现了一个小脚本目的是替换tail命令,它使用循环(我猜),但我无法理解它的功能。

使其仅在该*/部分之前匹配

第三部分是确保忽略的大小写仅匹配注释块结束之前的内容 ( */)。因此,最终,忽略大小写只会匹配/*和之间的内容*/。最终的命令将完全忽略注释块中写入的内容。

我没有对这部分进行真正的搜索,因为我没有解决前一点,在我看来,这个*/问题取决于/*前一个问题。


最后一部分:将所有这些放在一起

嗯,很明显我此刻完全失败了。


长话短说

我的问题是: sed 命令是什么,以便仅在文本文件中没有注释的情况下替换我们想要的任何内容?


附录

如果您知道使用任何其他语言更简单的方法,也非常受欢迎。因此,如果您知道如何使用 或其他任何东西来做到这一点awkpython请随时分享。

答案1

如果他们告诉你这是不可能的,你不应该相信他们。你应该然而,相信他们,如果他们告诉你这并不容易。

sed '\|*/|!{ s|/\*|\n&|              #if ! */ repl 1st /* w/ \n/*
     h;      s|foo|bar|g;/\n/!b      #hold; repl all foo/bar; if ! \n branch
     G;      s|\n.*\n||;:n           #Get; clear difference; :new label
     n;      \|*/|!bn;s|^|\n/*|      #new line; if ! */ branch new label
     };s|*/|\n&|g                    #repl all */ w/ \n*/
       s|foo|&\nbar|g;:r             #repl all foo w/ foo\nbar
       s|\(/\*[^\n]*\)\nbar|\1|g;tr  #repl all /*[^\n]*\nbar w/ foo
       s|foo\n\(b\)|\1|g             #repl all foo\nbar w/ bar
       s|^\n/.||;s|\n||g             #clear any \n inserts
'    <<\INPUT
asfoo   /* asdfooasdfoo


asdfasdfoo
asdfasdfoo
foo */foo /*foo*/ foo
/*.
foo*/
foo
hello

INPUT

输出

asbar   /* asdfooasdfoo


asdfasdfoo
asdfasdfoo
foo */bar /*foo*/ bar
/*.
foo*/
bar
hello

相关内容