代码之家  ›  专栏  ›  技术社区  ›  maaartinus

将所有已完成的替换更改为其他内容

  •  0
  • maaartinus  · 技术社区  · 7 年前

    在重写遗留应用程序时,我对 foo 通过 bar 与许多手动更改混合在一起。一些替换必须手动撤消,而且已经有许多其他替换 酒吧 原始代码中的。

    现在,我看到每个 foo公司 替换为 酒吧 实际上应该是 baz

    例如:

    • 旧文件:
      a staying "foo" and a replaced "foo" and a kept "bar"
    • 新建文件
      a staying "foo" and a replaced "bar" and a kept "bar"
    • 受通缉的
      a staying "foo" and a replaced "baz" and a kept "bar"

    想要采取的行动很简单:修复 foo公司 通过 酒吧 巴兹 .我想知道是否有一种简单的方法 git 或任何Linux工具。

    重新制定

    也许这句话更清楚:

    给定一个文件的两个版本,将 巴兹 在旧版本包含 foo公司 新版本包含 酒吧

    更多详细信息

    实际上有三个 整句话 替换为 不同的长度 喜欢

    perl -pe 's/\babc\b/pqrs/gi; s/\bdefg\b/uvw/gi; s/\bhi\b/xyz/g'
    
    2 回复  |  直到 7 年前
        1
  •  3
  •   Leon    7 年前

    您可以使用 --word-diff=porcelain 的模式 git diff (以及传递给 -U 选项,以保留更改之间的所有上下文),并使用足够简单的脚本处理其输出,以更正错误的替换。

    --word-diff[=<mode>] 显示单词diff,使用 <mode> 划界改变的单词。默认情况下,单词由空格分隔; 看见 --word-diff-regex 在下面这个 <模式> 默认为 plain 和 必须是以下内容之一:

    • 。。。
    • porcelain :使用专用于脚本使用的基于行的格式。添加/删除/未更改的运行以通常的方式打印 统一的差异格式,以+/-/``字符开头 线的起点和延伸到线的终点。换行符 在输入中,由颚化符表示 ~ 在自己的线路上。

    下面是一个原型 sed -基于上述方法的实施。

    用法 :

    fix_wrong_replacements path revision replacement_fix

    哪里

    • 路径 是工作树中文件的(相对)路径
    • 修订 是必须修复的错误替换的修订版本
    • 替换\u修复 是表单的字符串

      /orig_pattern/incorrect_replacement_str/correct_replacement_str/

    影响 :

    假设文件的工作副本位于 路径 比较时 至其承诺修订版 修订 包含替换的结果 某些实例 orig_pattern 具有 incorrect_replacement_str ,则, 确定这些替换并将其更改为 correct_replacement_str

    示例 :

    # In last two commits (and, maybe, in the working copy) some "int"s
    # were incorrectly changed to "unsigned", now change those to "long"
    $myname main.c HEAD~2 /int/unsigned/long/
    
    # In the working copy of somefile.txt all "abc" case-insensitive words
    # were changed to "pqrs", now change them to "xyz"
    $myname somefile.txt HEAD '/[aA][bB][cC]/pqrs/xyz/'
    

    已知限制/问题 :

    • 它适用于单个文件。要修复提交、提交范围或本地更改中的所有错误替换,必须标识更改文件的列表,并在循环中为所有文件调用此脚本。

    • 如果在原始(错误)更换过程中使用了不区分大小写的模式,则 orig\U模式 部分 替换\u修复 参数必须使用 [aA] ,则, [bB] 等,每个字母的正则表达式原子。

    • 不处理与其他更改直接相邻的替换。

    • 有时可能会添加多余的空行(因为 git diff --word-diff )

    修复\u错误的\u替换 :

    #!/usr/bin/env bash
    
    myname="$(basename "$0")"
    
    if [ $# -ne 3 ]
    then
        cat<<END
    Usage:
    
        $myname <path> <revision> <replacement_fix>
    
    where
        - <path> is the (relative) path of the file in the working tree
        - <revision> is the revision since which the wrong replacements that
          must be fixed were made
        - <replacement_fix> is a string of the form
    
            /orig_pattern/incorrect_replacement_str/correct_replacement_str/
    
    Effects:
    
        Assuming that the working copy of the file at <path> when compared
        to its committed revision <revision> contains results of replacing
        certain instances of <orig_pattern> with <incorrect_replacement_str>,
        identifies those replacements and changes them to <correct_replacement_str>.
    
    
    Examples:
    
        # In last two commits (and, maybe, in the working copy) some "int"s
        # were incorrectly changed to "unsigned", now change those to "long"
        $myname main.c HEAD~2 /int/unsigned/long/
    
        # In the working copy of somefile.txt all "abc" case-insensitive words
        # were changed to "pqrs", now change them to "xyz"
        $myname somefile.txt HEAD '/[aA][bB][cC]/pqrs/xyz/'
    END
        exit 1
    fi
    
    file="$1"
    revision="$2"
    s=(${3//// })
    orig_pattern="${s[0]}"
    incorrect_replacement="${s[1]}"
    correct_replacement="${s[2]}"
    
    pat="-$orig_pattern\n+$incorrect_replacement"
    
    git_word_diff()
    {
        git diff -U100000                                       \
                 --word-diff=porcelain                          \
                 --word-diff-regex='[[:alpha:]][[:alnum:]]*'    \
                 "$@"
    }
    
    
    word_diff_file="$(mktemp)"
    trap "rm $word_diff_file" EXIT
    
    git_word_diff "$revision" -- "$file" > "$word_diff_file"
    sed -n -e '
        1,5 d;
    
        /^-/ N;
        /\n~$/ d;
        /\n[- ]/ D;
    
        /^'"$pat"'$/ {x;G;s/\n'"$pat"'$/'"$correct_replacement"'/;x;d;};
        /^-.*\n+/ {s/^-.*\n+//;H;x;s/\n//;x;d;};
    
        /^~$/ {s/.*//;x;p;d;};
    
        {s/^.//;H;x;s/\n//;x;};
    ' "$word_diff_file" > "$file"
    
        2
  •  -2
  •   kavita    7 年前

    替换foo:grep-rl“foo”xargs sed-i’s/foo/bar/g

    要替换条形图:grep-rl“bar”。|xargs sed-i’s/bar/baz/g