在多个文件中执行类似替换(对于 diff 来说不够简单)的智能方法?

在多个文件中执行类似替换(对于 diff 来说不够简单)的智能方法?

我有一堆文件(45 个,太多了,无法手动编辑它们而不会发疯),它们都需要相同的更改(如本问题末尾的三个差异所示)。

大多数用于在命令行上进行搜索和替换的工具仅支持逐行替换,因此它们不起作用。

是否有一些可用的命令行工具可以完成这项工作?基本上执行多行正则表达式搜索和反向引用替换,而不将整个正则表达式推入一行(即应该从文件或标准输入中读取)应该足够了,但也许有更好的解决方案来做到这一点......


--- a/editfile.html
+++ b/editfile.html
@@ -60,7 +60,5 @@

 <script type="text/javascript">
-    $(document).ready(function() {
-        editFileInit(opts);
-    });
+    initPage('editFile', opts);
 </script>
 {% endblock %}
diff --git a/gallery.html b/gallery.html
index 4a07f70..81084ad 100644
--- a/exodus/templates/gallery.html
+++ b/exodus/templates/gallery.html
@@ -87,9 +87,7 @@

     <script type="text/javascript">
-        $(document).ready(function() {
-            galleryInit({
-                editTitleUrl: {{ csrf_url_for('gallery_editpictitle')|tojson|safe }},
-                delPicUrl: {{ csrf_url_for('gallery_delpic')|tojson|safe }}
-            });
+        initPage('gallery', {
+            editTitleUrl: {{ csrf_url_for('gallery_editpictitle')|tojson|safe }},
+            delPicUrl: {{ csrf_url_for('gallery_delpic')|tojson|safe }}
         });
     </script>
diff --git a/stream_history.html b/stream_history.html
index 783fea4..ea837fa 100644
--- a/exodus/templates/stream_history.html
+++ b/exodus/templates/stream_history.html
@@ -25,8 +25,6 @@

     <script type="text/javascript">
-        $(document).ready(function() {
-            songHistoryInit({
-                dataURL: {{ url_for('stream_history_json')|tojson|safe }}
-            });
+        initPage('songHistory', {
+            dataURL: {{ url_for('stream_history_json')|tojson|safe }}
         });
     </script>

如果不保留缩进,那么这不是一个大问题。

答案1

在 vi 中使用 :ex 模式可以做的任何事情都可以变成脚本编辑

ed就像vi但没有那些烦人的用户友好界面妨碍你并减慢你的速度。

抛开开玩笑不谈,ed它是一个用于文本文件脚本编辑的有用工具。

答案2

让我们保持简单。这些文件适合内存中,因此不必费心逐行读取它们或类似的内容。珀尔的-p(迭代文件内容)开关和-0777“吸食模式”(一次读取整个文件,而不是逐行读取)很方便。

作用于多个文件,使用起来很方便-i(就地编辑文件)。

要执行替换,请使用s替换运算符。看perlre#修饰符有关修饰符的解释msx

perl -0777 -i.orig -p -e '
    s[
      ^(\s+)                                  # indentation
      \Q$(document).ready(function() {\E\n
      \s*(\w+)Init                            # function name
      (\(((?:(?>[^()]+)|(?3))*)\))            # balanced parentheses
      ;\n\s*\}\);
     ][
       ${1}initPage(\x27$2\x27, $3);
     ]msx;
' **/*.js

**/*.js.js递归匹配当前目录及其子目录中的所有文件。这在 zsh 中是开箱即用的。如果您使用 bash,请将其添加shopt -s globstar到您的~/.bashrc.

(未经测试,您可能需要稍微调整正则表达式。)

答案3

将输出转储到标准输出,因此不会将文件丢弃。

#!/usr/bin/perl

use strict;
use warnings;

# Slurp our input...
my $text = do {local $/; <> };

# Extract the varying parts: foo and bar, for fooInit(bar)
my ($init_prefix, $init_opts) = $text =~ m/([a-zA-Z0-9]+)Init\(([^;]+;)/m;

# Construct the replacement: fooInit(bar) -> initPage('foo', bar)
my $replace_with = "initPage('$init_prefix', $init_opts";

# Target the text to replace...
my $to_replace = '\$\(document.*;';

# Perform the replacement;
$text =~ s/$to_replace/$replace_with/gs;

print $text;

对您的所有三个示例进行了测试。尽管代码是正确的,并且替换的第一行将在正确的位置开始,但替换行的缩进不正确。

$ perl replace.pl 1.js

script type="text/javascript">
    initPage('editFile', opts);
</script>
{% endblock %}

$ perl replace.pl 2.js

 <script type="text/javascript">
    initPage('gallery', {
            editTitleUrl: {{ csrf_url_for('gallery_editpictitle')|tojson|safe }},
            delPicUrl: {{ csrf_url_for('gallery_delpic')|tojson|safe }}
        });
</script>

$ perl replace.pl 3.js

 <script type="text/javascript">
    initPage('songHistory', {
            dataURL: {{ url_for('stream_history_json')|tojson|safe }}
        });
</script>

相关内容