Vra*_*all 6 sed text-processing regular-expression
我正在尝试使用正则表达式创建 sed 命令,以便仅在没有注释的情况下替换文本文件中的某些内容,但由于我几乎不了解 sed 命令的知识,我遇到了一些麻烦。
我为问题的一小部分找到了解决方案,但有些还不够完整,或者我无法将它们放在一起。TL; DR 版本在最后可用。
让我们先确定我的最终目标
只有在没有注释的情况下,我才想在文本文件中匹配任何内容(如任何常规正则表达式(呵呵))。因为我想为多种语言做这件事,让我们只看常见的 C 注释。
因此,在这种情况下,可以以不同方式对单词或行进行注释。我们//
只有评论线路上的下一个内容,我们还有/* */
评论块。
环境
我目前正在使用仅支持 POSIX sed 的 Mac OSX,但我安装了一个我发现更好的 GNU-sed。(感谢Homebrew
. 包是gnu-sed
,命令是gsed
。)所以,如果您喜欢使用其中一种或另一种,我可以使用它们。
我在写这篇文章时假设使用了 GNU-sed。
忽略一个案例
第一个问题,如何忽略某些情况。我在这个话题中很容易地发现了这一点。
现在,这//
部分对我来说似乎很容易做,我只需要添加一个OR ( |
)条件即可将其与另一个条件连接起来。
它看起来像这样:
sed -E "/\/\/.*/! s/foo/bar/" file
Run Code Online (Sandbox Code Playgroud)
然后,如果输入文件是:
foo
42
test
//foo
//42
// foo
//something foo
foo
42
something foo
foo
Run Code Online (Sandbox Code Playgroud)
输出是:
bar
42
test
//foo
//42
// foo
//something foo
bar
42
something bar
bar
Run Code Online (Sandbox Code Playgroud)
所以现在,我只想把我的反思集中在/* */
评论块上。
通过多行匹配
第二个问题,如何通过多行使正则表达式匹配。嗯,我认为这是主要问题。我找到了这个话题在讨论如何仅通过一个新行字符进行匹配。好吧,我花了一点时间才明白它是如何工作的。但是这部分解决方案给我带来了一个新问题和新问题。
它显然只能忽略一个新行 ( \n
)。所以我现在想要做同样的事情,但是对于未知数量的行(从 0 到无限 ( *
))。我敢打赌我必须遍历这些行,但这就是我被卡住的地方,因为我对 sed 的命令一无所知,这对我来说真的很尴尬。
在我的搜索过程中,我发现了一个用于替换命令的小脚本,tail
它使用了一个循环(我猜),但我无法理解它的功能。
使它只在*/
零件之前匹配
第三部分是确保忽略的大小写仅匹配注释块 ( */
)结尾之前的内容。因此,最后,ignore case 只会匹配/*
和之间的内容*/
。最后的命令将完全忽略注释块中写入的内容。
我没有对这部分进行真正的搜索,因为我没有解决上一点,在我看来,这个*/
问题取决于上/*
一个问题。
最后一部分:将所有这些放在一起
嗯,很明显我现在完全失败了。
TL; 博士
我的问题是: sed 命令是什么,以便仅在没有注释的情况下替换文本文件中我们想要的任何内容?
附录
如果您知道使用任何其他语言的更简单的方法,也非常欢迎。所以,如果你知道如何与做awk
,python
或者别的什么,随时分享。
mik*_*erv 10
如果他们告诉你这是不可能的,你不应该相信他们。然而,如果他们告诉你这并不容易,你应该相信他们。
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
Run Code Online (Sandbox Code Playgroud)
asbar /* asdfooasdfoo
asdfasdfoo
asdfasdfoo
foo */bar /*foo*/ bar
/*.
foo*/
bar
hello
Run Code Online (Sandbox Code Playgroud)