bash 是否有 'git sed' 或等价物?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9651898/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 01:45:41  来源:igfitidea点击:

Is there a 'git sed' or equivalent?

linuxgitbashsed

提问by Clayton Stanley

Let's say I want to rename a method in source code contained in a git repository. I could do this by hand, but the method name might be in multiple places (e.g., unit test, documentation, actual method). To check where the method is used, I use 'git grep'. I get 'git grep' to show only lines that I want to change, and then I don't have a workflow to automatically change those lines.

假设我想重命名包含在 git 存储库中的源代码中的方法。我可以手动执行此操作,但方法名称可能位于多个位置(例如,单元测试、文档、实际方法)。要检查使用该方法的位置,我使用了“git grep”。我得到 'git grep' 只显示我想更改的行,然后我没有自动更改这些行的工作流程。

I'm looking for an automated way (hopefully using git tools) to do this last step. I was hoping there was some sort of 'git sed' or equivalent, but I can't find any.

我正在寻找一种自动化的方式(希望使用 git 工具)来完成最后一步。我希望有某种“git sed”或类似的东西,但我找不到任何东西。

The interface I'm thinking would be nice: git sed 's/old-method-name/new-method-name/g'

我想的界面会很好: git sed 's/old-method-name/new-method-name/g'

采纳答案by Noufal Ibrahim

You could do a

你可以做一个

for i in $(git grep --full-name -l old_method_name)
do
 perl -p -i -e 's/old_method_name/new_method_name/g' $i
done

stick that in a file somewhere and then alias it as git sedin your config.

将其粘贴在某个文件中,然后将其作为git sed您的配置中的别名。

Update:The comment by tchrist below is a much better solution since it prevents perl from spawning repeatedly.

更新:下面 tchrist 的评论是一个更好的解决方案,因为它可以防止 perl 重复生成。

回答by Greg Hewgill

You could use git ls-filesin combination with xargsand sed:

您可以git ls-filesxargs和结合使用sed

git ls-files -z | xargs -0 sed -i -e 's/old-method-name/new-method-name/g'

回答by Clayton Stanley

Thanks to both Noufal and Greg for their posts. I combined their solutions, and found one that uses git grep (more robust than git ls-files for my repo, as it seems to list only the files that have actual src code in them - not submodule folders for example), and also has the old method name and new method name in only one place:

感谢 Noufal 和 Greg 的帖子。我结合了他们的解决方案,并找到了一个使用 git grep(比 git ls-files 对我的 repo 更强大,因为它似乎只列出了其中包含实际 src 代码的文件 - 例如,而不是子模块文件夹),并且还具有旧方法名称和新方法名称仅在一处:

In the [alias]block of my ~/.gitconfigfile:

[alias]我的~/.gitconfig文件块中:

sed = ! git grep -z --full-name -l '.' | xargs -0 sed -i -e

To use:

使用:

git sed 's/old-method-name/new-method-name/ig'

回答by Mr Fooz

Here's a solution that combines those of of Noufal and claytontstanley and avoids touching files that won't change.

这是一个结合了 Noufal 和 Claytontstanley 的解决方案并避免接触不会改变的文件的解决方案。

In the [alias]block of my ~/.gitconfigfile:

[alias]我的~/.gitconfig文件块中:

psed = !sh -c 'git grep --null --full-name --name-only --perl-regexp -e \"\" | xargs -0 perl -i -p -e \"s///g\"' -

To use:

使用:

git psed old_method_name new_method_name

回答by Omar Al-Ithawi

Yes, there's. In Ubuntu the package git-extrasprovides the command. Install it:

是的,有。在 Ubuntu 中,该软件包git-extras提供了命令。安装它:

$ sudo apt-get install git-extras

Use it like bellow e.g. to correct a spelling issue quickly:

像下面一样使用它,例如快速纠正拼写问题:

$ git sed 'qoute' 'quote'

Unfortunately it doesn't support file filters like what git grep does:

不幸的是,它不支持像 git grep 那样的文件过滤器:

$ git grep -e 'class' -- '*.py'

The same functionality also exists on Mac and other operating systems. Checkout its installation page.

Mac 和其他操作系统上也存在相同的功能。查看其安装页面

回答by VonC

Note that starting git 2.1 (Q3 2014), you can set "full-name" by default for git grep.
(See commit 6453f7bby Andreas Schwab)

请注意,从git 2.1 (Q3 2014) 开始,您可以full-name默认为git grep.
(参见提交6453f7b安德烈亚斯施瓦布

"git grep" learned grep.fullnameconfiguration variable to force "--full-name" to be default.
This may cause regressions on scripted users that do not expect this new behaviour.

git grep”学习grep.fullname配置变量以强制“ --full-name”为默认值。
这可能会导致脚本化用户不期望这种新行为的回归。

That means the previous solutions can benefit from:

这意味着以前的解决方案可以受益于:

git config grep.full-name true

And use:

并使用:

psed = !sh -c 'git grep --null --name-only --perl-regexp -e \"\" | xargs -0 perl -i -p -e \"s///g\"' -

回答by Dan Aloni

See git-search-replaceon github - it's designed for this exactly.

请参阅github 上的git-search-replace- 它正是为此而设计的。

回答by Mark Raymond

I have written a git sed which supports file filtering:

我写了一个支持文件过滤的 git sed:

#!/bin/bash

split=$(($# + 1))

for i in $(seq 1 $#); do
   if [[ "${!i}" = "--" ]]; then
       split=$i
   fi
done

git ls-files -z "${@:$split:$#}" | xargs -0 sed -b -i "${@:1:$(($split - 1))}"

(You probably don't want the -bparameter on non-Windows platforms; it's necessary on Windows to preserve Windows-style newlines.)

(您可能不希望-b在非 Windows 平台上使用该参数;在 Windows 上有必要保留 Windows 样式的换行符。)

You can then add an alias in your .gitconfig:

然后,您可以在您的.gitconfig:

[alias]
    sed = ! <path to git-sed>

so that you can use it like git sed -e <your expression> -- <path filter>.

这样你就可以像git sed -e <your expression> -- <path filter>.

回答by ext

Unhappy with most other solutions provided (which is basically just a string-replace on git tracked files) I wrote my own script: git-sed.

对提供的大多数其他解决方案(基本上只是 git 跟踪文件的字符串替换)不满意,我编写了自己的脚本:git-sed

  • It supports any expression sed supports (e.g git sed '1{/^$/d}')
  • Can run on a subset of paths in the repo (git sed 's/foo/bar' src tests)
  • Multiple expressions (git sed -e 's/foo/bar' -e '/bar/d').
  • etc...
  • 它支持 sed 支持的任何表达式(例如git sed '1{/^$/d}'
  • 可以在 repo ( git sed 's/foo/bar' src tests) 中的路径子集上运行
  • 多个表达式 ( git sed -e 's/foo/bar' -e '/bar/d')。
  • 等等...

Just drop it anywhere in PATHto use it or add an alias pointing to the full path.

只需将它放在任何地方PATH即可使用它或添加一个指向完整路径的别名。