I want to perform a batch replace operation on a project by following some rules. For e.g. I am taking notes in the code like this:
我想按照一些规则对项目执行批量替换操作。对于例如我在代码中记笔记如下:
On every code piece, which is commented like this, I want to perform a replace operation, which will replace the input code piece with the output code piece in the following examples:
在每个代码片段上,这样注释,我想执行一个替换操作,它将输入代码片替换为以下示例中的输出代码片:
Input 1:
//+
a++;
//+(+SomeException$SomeMessage)
Output 1:
try
{
a++;
}
catch (AnException)
{
throw;
}
catch (Exception ex)
{
throw new SomeException("SomeMessage", "15", ex);
}
Input 2:
//+
a++;
//-(+InvalidOperationException$SomeMessage)
Output 2:
try
{
a++;
}
catch (InvalidOperationException ex)
{
throw new AnException("SomeMessage", "16", ex);
}
Input 3:
//+
a++;
//-(SomeMessage)
Output 3:
try
{
a++;
}
catch (Exception ex)
{
throw new AnException("SomeMessage", "17", ex);
}
The magic numbers (15, 16, 17) will increase for each code piece commented like this. I know this is not the best practice but I am not making the decisions and I am expected to handle exceptions like this, so I thought I can ease the pain by taking notes and batch replacing in the end. What is the best way to do this? Should I write my own code to perform replaces or is there some regex replace tool or something like that exist that can automatically make this for me?
对于像这样评论的每个代码段,幻数(15,16,17)将增加。我知道这不是最好的做法,但我没有做出决定,我希望能处理这样的例外情况,所以我想我最终可以通过记笔记和批量替换来减轻痛苦。做这个的最好方式是什么?我应该编写自己的代码来执行替换,还是有一些正则表达式替换工具或类似的东西可以自动为我做这个?
Update: This is a one time job and my magic number has to be globally unique. So if it was 25 for the last match in a file, it must be 26 for the first match in the next file.
更新:这是一次性工作,我的幻数必须是全球唯一的。因此,如果文件中的最后一个匹配为25,则下一个文件中的第一个匹配必须为26。
6 个解决方案
#1
What is the best way to do this? Should I write my own code to perform replaces or is there some regex replace tool or something like that exist that can automatically make this for me?
做这个的最好方式是什么?我应该编写自己的代码来执行替换,还是有一些正则表达式替换工具或类似的东西可以自动为我做这个?
I'd write a little program in C++ or C# to do this. There are presumably other tools and script languages that can do it; but given that it's a trivial job in C++ or C# and given that I aready know how to do it in these languages, why not?
我会用C ++或C#编写一个小程序来做这件事。可能有其他工具和脚本语言可以做到这一点;但鉴于它在C ++或C#中是一项微不足道的工作,并且我知道如何用这些语言来做,为什么不呢?
I don't know what you mean by the "best" way, but for me at least this would be one of the easiest ways.
我不知道你的“最佳”方式是什么意思,但对我来说至少这将是最简单的方法之一。
#2
This looks like a simple language that you're going to compile into another language that looks like Java. A compiler is the right tool for a job like this, especially because you need to keep around the state of the current magic number. It also seems likely that whoever is making the decisions would want to add new features to the language, in which case a solution glued together with regular expressions might not work properly.
这看起来像一种简单的语言,您将要编译成另一种看起来像Java的语言。编译器是这样的工作的正确工具,特别是因为你需要保持当前幻数的状态。似乎做出决定的人也希望在语言中添加新功能,在这种情况下,使用正则表达式粘合在一起的解决方案可能无法正常工作。
If I'm right about what you really want, your question is reduced to the problem of "How do I write a Domain Specific Language?" I'm not sure what the best method would be for this, but if you know Perl you could probably put together a solution with Parse::RecDescent.
如果我对你真正想要的是对的,那么你的问题就变成了“如何编写领域特定语言?”的问题。我不确定最好的方法是什么,但是如果你知道Perl,你可以用Parse :: RecDescent组合一个解决方案。
I think it's possibly to do this with scripting and regular expressions, but this is the type of problem for which compilers were invented. If you end up making something hacky, God help the person that has to maintain it after you! :)
我认为这可能是通过脚本和正则表达式来实现的,但这是编译器发明的问题类型。如果你最终制造了一些hacky,那么上帝帮助那些必须在你之后保持它的人! :)
#3
You could write a CodeSmith template that reads that input and outputs that output. But, I'm not sure you could do it in-line. That is, you would need a file of just inputs and then your template could give you the file of outputs. I'm not sure if that acceptable tho.
您可以编写一个CodeSmith模板来读取该输入并输出该输出。但是,我不确定你能否在线进行。也就是说,您需要一个只有输入的文件,然后您的模板可以为您提供输出文件。我不确定那是否可以接受。
#4
There's a lot of ways you could do this, even though you probably shouldn't (as you seem to realize, this will just result in meaningless exceptions). Nevertheless, here's a sed/sh combo to do the first one. It doesn't handle the autonumbering or your other variants. I'll leave that as an exercise for the OP.
有很多方法可以做到这一点,即使你可能不应该这样做(正如你似乎意识到的那样,这只会导致毫无意义的例外)。不过,这里有一个sed / sh组合来做第一个。它不处理自动编号或您的其他变体。我将把它作为OP的练习。
P1='\/\/+'; P2='\(.*\)'; P3='\/\/+(+\([^$]*\)$\(.*\))';
echo 'foo()\n//+\na++\n//+(+SomeException$Message)'|sed ' /'$P1'/ { N; /'$P2'/ { N; /'$P3'/ { s/'$P1'\n'$P2'\n'$P3'/try\n{\n\t\1\n}\ncatch (AnException)\n{\n\tthrow;\n}\ncatch (Exception ex)\n{\n\tthrow new \2("\3", "0", ex);\n}/ } } } '
The echo is just a test string.
回声只是一个测试字符串。
#5
As an Emacs user, for a one time job I'd do this by defining keyboard macros, then use set/increment/insert-register for the autonumbering magic. There shouldn't really be any need for writing your own elisp functions.
作为Emacs用户,对于一次性工作,我通过定义键盘宏来执行此操作,然后使用set / increment / insert-register进行自动编号魔术。不应该真正需要编写自己的elisp函数。
Though if you need to perform this on more than just a couple of files, you'll probably be better off writing a script to do the job.
虽然如果你需要在不仅仅是几个文件上执行此操作,那么编写脚本来完成这项工作可能会更好。
#6
If you do not happen to use an IDE like Emacs (as answered by many) with strong regex support I would write a little script. Note that text manipulation is in general more a scripting operation, e.g. Perl, Ruby, due to regex support in the language itself. On the other hand if you are very familiar with say Java Pattern
, then writing it in Java is propably the fastest solution, even if you need more overhead esp. for a one time operation.
如果您没有使用像Emacs这样的IDE(由许多人回答)具有强大的正则表达式支持,我会编写一个小脚本。注意,文本操作通常更像是脚本操作,例如, Perl,Ruby,由于语言本身的正则表达式支持。另一方面,如果您非常熟悉Java Pattern,那么使用Java编写它可能是最快的解决方案,即使您需要更多的开销esp。一次性操作。
So a litte Ruby script might look like that (beware, I did not test it):
所以一个小小的Ruby脚本可能看起来像那样(小心,我没有测试它):
$cnt = 1
IO.readlines(filename).collect { |line|
if line =~ /^\s*\/\/\+\s*$/
$cnt += 1
["try\n", "{\n" ]
elsif line =~ /^\s*\/\/\+\(\+(.+)\$(.+)\)\s*/
["}\n", "catch (#{$1} ex)\n", "{\n",
"throw new AnException(\"#{$2}\", \"#{$cnt}\", ex);\n", "}\n"]
# propably more else for all cases
else
line
end
}.flatten
# save the file again
#1
What is the best way to do this? Should I write my own code to perform replaces or is there some regex replace tool or something like that exist that can automatically make this for me?
做这个的最好方式是什么?我应该编写自己的代码来执行替换,还是有一些正则表达式替换工具或类似的东西可以自动为我做这个?
I'd write a little program in C++ or C# to do this. There are presumably other tools and script languages that can do it; but given that it's a trivial job in C++ or C# and given that I aready know how to do it in these languages, why not?
我会用C ++或C#编写一个小程序来做这件事。可能有其他工具和脚本语言可以做到这一点;但鉴于它在C ++或C#中是一项微不足道的工作,并且我知道如何用这些语言来做,为什么不呢?
I don't know what you mean by the "best" way, but for me at least this would be one of the easiest ways.
我不知道你的“最佳”方式是什么意思,但对我来说至少这将是最简单的方法之一。
#2
This looks like a simple language that you're going to compile into another language that looks like Java. A compiler is the right tool for a job like this, especially because you need to keep around the state of the current magic number. It also seems likely that whoever is making the decisions would want to add new features to the language, in which case a solution glued together with regular expressions might not work properly.
这看起来像一种简单的语言,您将要编译成另一种看起来像Java的语言。编译器是这样的工作的正确工具,特别是因为你需要保持当前幻数的状态。似乎做出决定的人也希望在语言中添加新功能,在这种情况下,使用正则表达式粘合在一起的解决方案可能无法正常工作。
If I'm right about what you really want, your question is reduced to the problem of "How do I write a Domain Specific Language?" I'm not sure what the best method would be for this, but if you know Perl you could probably put together a solution with Parse::RecDescent.
如果我对你真正想要的是对的,那么你的问题就变成了“如何编写领域特定语言?”的问题。我不确定最好的方法是什么,但是如果你知道Perl,你可以用Parse :: RecDescent组合一个解决方案。
I think it's possibly to do this with scripting and regular expressions, but this is the type of problem for which compilers were invented. If you end up making something hacky, God help the person that has to maintain it after you! :)
我认为这可能是通过脚本和正则表达式来实现的,但这是编译器发明的问题类型。如果你最终制造了一些hacky,那么上帝帮助那些必须在你之后保持它的人! :)
#3
You could write a CodeSmith template that reads that input and outputs that output. But, I'm not sure you could do it in-line. That is, you would need a file of just inputs and then your template could give you the file of outputs. I'm not sure if that acceptable tho.
您可以编写一个CodeSmith模板来读取该输入并输出该输出。但是,我不确定你能否在线进行。也就是说,您需要一个只有输入的文件,然后您的模板可以为您提供输出文件。我不确定那是否可以接受。
#4
There's a lot of ways you could do this, even though you probably shouldn't (as you seem to realize, this will just result in meaningless exceptions). Nevertheless, here's a sed/sh combo to do the first one. It doesn't handle the autonumbering or your other variants. I'll leave that as an exercise for the OP.
有很多方法可以做到这一点,即使你可能不应该这样做(正如你似乎意识到的那样,这只会导致毫无意义的例外)。不过,这里有一个sed / sh组合来做第一个。它不处理自动编号或您的其他变体。我将把它作为OP的练习。
P1='\/\/+'; P2='\(.*\)'; P3='\/\/+(+\([^$]*\)$\(.*\))';
echo 'foo()\n//+\na++\n//+(+SomeException$Message)'|sed ' /'$P1'/ { N; /'$P2'/ { N; /'$P3'/ { s/'$P1'\n'$P2'\n'$P3'/try\n{\n\t\1\n}\ncatch (AnException)\n{\n\tthrow;\n}\ncatch (Exception ex)\n{\n\tthrow new \2("\3", "0", ex);\n}/ } } } '
The echo is just a test string.
回声只是一个测试字符串。
#5
As an Emacs user, for a one time job I'd do this by defining keyboard macros, then use set/increment/insert-register for the autonumbering magic. There shouldn't really be any need for writing your own elisp functions.
作为Emacs用户,对于一次性工作,我通过定义键盘宏来执行此操作,然后使用set / increment / insert-register进行自动编号魔术。不应该真正需要编写自己的elisp函数。
Though if you need to perform this on more than just a couple of files, you'll probably be better off writing a script to do the job.
虽然如果你需要在不仅仅是几个文件上执行此操作,那么编写脚本来完成这项工作可能会更好。
#6
If you do not happen to use an IDE like Emacs (as answered by many) with strong regex support I would write a little script. Note that text manipulation is in general more a scripting operation, e.g. Perl, Ruby, due to regex support in the language itself. On the other hand if you are very familiar with say Java Pattern
, then writing it in Java is propably the fastest solution, even if you need more overhead esp. for a one time operation.
如果您没有使用像Emacs这样的IDE(由许多人回答)具有强大的正则表达式支持,我会编写一个小脚本。注意,文本操作通常更像是脚本操作,例如, Perl,Ruby,由于语言本身的正则表达式支持。另一方面,如果您非常熟悉Java Pattern,那么使用Java编写它可能是最快的解决方案,即使您需要更多的开销esp。一次性操作。
So a litte Ruby script might look like that (beware, I did not test it):
所以一个小小的Ruby脚本可能看起来像那样(小心,我没有测试它):
$cnt = 1
IO.readlines(filename).collect { |line|
if line =~ /^\s*\/\/\+\s*$/
$cnt += 1
["try\n", "{\n" ]
elsif line =~ /^\s*\/\/\+\(\+(.+)\$(.+)\)\s*/
["}\n", "catch (#{$1} ex)\n", "{\n",
"throw new AnException(\"#{$2}\", \"#{$cnt}\", ex);\n", "}\n"]
# propably more else for all cases
else
line
end
}.flatten
# save the file again