Linux 为什么这个git/grep/vim快捷方式bash代码不能像广告中那样工作?

Linux 为什么这个git/grep/vim快捷方式bash代码不能像广告中那样工作?,linux,bash,git,vim,Linux,Bash,Git,Vim,在本bash教程的最后,Spencer Krum展示了一个简单的技巧:如何在vim中打开一个位于前一个“git grep-n”搜索字符串所在行号处的文件。它看起来很整洁,但他的代码并不像我在两个不同的linux机器上所描述的那样工作。它总是打开一个空白文件 我的步骤: 首先,我确保对git进行了初始化,并将目录中的文件放入grep中。例如,我有一个somefile.txt,其中有三行字: 其 a 神秘的 然后我运行:gitinit;吉特加。;git提交 然后,修改.bashrc文件以重新定义

在本bash教程的最后,Spencer Krum展示了一个简单的技巧:如何在vim中打开一个位于前一个“git grep-n”搜索字符串所在行号处的文件。它看起来很整洁,但他的代码并不像我在两个不同的linux机器上所描述的那样工作。它总是打开一个空白文件

我的步骤:

首先,我确保对git进行了初始化,并将目录中的文件放入grep中。例如,我有一个somefile.txt,其中有三行字:

  • a
  • 神秘的
然后我运行:
gitinit;吉特加。;git提交

然后,修改.bashrc文件以重新定义vim,如下所示。确保在完成时找到.bashrc文件的源代码:
source~/.bashrc

最后,运行git grep-n命令,其中包含一个搜索词,您知道它位于当前工作目录的git目录中的一个文件中。最后,运行vim。它应该用光标在搜索词行打开您的文件。但事实并非如此:
git grep-n神秘;vim

#Spencers Original
vim () {
    last_command=$(history | tail -n 2 | head -n 1)
    if [[ $last_command =~ 'git grep' ]] && [[ "$*" =~ :[0-9]+:$ ]]; then
        line_number=$(echo $* | awk -F: '{print $(NF-1)}')
        /usr/bin/vim +${line_number} ${*%:${line_number}:}
    else
        /usr/bin/vim "$@"
    fi
}
为了得到期望的结果,我必须在第一个if语句的第二个子句中简化正则表达式,并创建一些临时变量来运行额外的eval逻辑

以下是我修改后的代码:

#My revised version
vim () { 
    last_command=$(history | tail -n 2 | head -n 1)

    rempws="${last_command#*"  "}"
    remtws="${rempws%*" "}"

    file_name="$(eval $remtws | awk -F: '{print $(NF-2)}')"
    line_number="$(eval $remtws | awk -F: '{print $(NF-1)}')"

    if [[ $last_command =~ 'git grep' ]] && [[ $line_number =~ [0-9] ]]
    then
        /usr/bin/vim +${line_number} ${file_name}
    else
        /usr/bin/vim "$@"
    fi
}
这与2015年以来的bash更新有关吗?我认为它与git无关,因为我的git grep-n命令确实返回了一个字符串,格式为'somefile.txt:3:奥秘'。观众中的每个人都喜欢它,而且它仍然在github上以不起作用的形式出现,所以我担心我错过了bash的一些基本功能


告诉我为什么我这么笨。

好吧,我终于明白这是怎么回事了

他的代码从未真正打算以某种方式访问
git grep
命令的输出

相反,这是一种认识,在
git grep
之后,您可能想要打开其中一个结果

但是,在他的工作流程中,他仍然依赖于将
git grep
结果复制粘贴到Vim命令行中

唯一的区别是,就在
git grep
之后,您可以向Vim传递一个文件名,其行号由
分隔,而不必传递两个单独的参数

在他的示例中,
git grep
的结果从以下内容开始:

CHANGELOG.rst:75: ...
因此,如果在下一个命令执行时:

$ vim CHANGELOG.rst:75:
(假设您从
git grep
结果中复制了最后一部分。)

然后bash函数将触发此命令:

$ vim +75 CHANGELOG.rst
将在第75行打开此文件

如果您喜欢这个特性的想法,那么一个更简洁的实现方法就是安装并启用Vim插件,它在Vim本身中实现了对那种文件名+行号参数的支持

(另外,没有充分的理由只在
git grep
之后识别
file:line
语法。如果您想要这种行为,最好总是得到它,而不仅仅是有时。它应该是一致的。)

一个更好的选择是使用Vim的特性,它正是为这种情况而设计的。您可以手动设置
'grepprg'
以使用适当的参数调用
git grep
,也可以采用一个插件,例如,它实现了一个
:Ggrep
命令,该命令调用
git grep
,并使用快速修复列表显示结果


正如@romainl所指出的,您可能还想研究一下,这是一个git命令,您可以在系统上启用它,让git找到感兴趣的位置(例如
git grep
git diff
输出),并让git自己在Vim中打开这些结果(适当时使用快速修复列表)

我不认为你是这里最笨的人。不要在你的生产环境中使用这种垃圾代码。而且,如果你真的在这样一个回购协议中四处奔波,只需安装Survious插件,它就可以用例如
:Git grep
和许多其他Git命令做令人惊讶的好事。例如,在编辑跟踪文件时说
:Git dull
。它的文档将基本上偿还您投入的任何时间。
$vim-q据我所知,作者使用的函数如下:1。do
$git grep-n foo
,2。将
path/to/filename.ext:23:
从结果中复制,3。执行
$vim
,4。将路径粘贴到/filename.ext:23:
,5。按回车键。如果用这种方式,他的功能可以预期的正常工作。我同意,这里的掌声似乎是不必要的。这就形成了一个笨拙的工作流程。在一个相关的注释中,我建议看一看(我还没有向上游提交)如何在Vim中打开各种Git“东西”:
$Git jump grep foo
。他说“你给我一些带有冒号的东西了吗?”但他说的是你,用户把它作为一个论据,而不是你(它?)
git grep
给Vim任何东西。。。我可以看到代码神奇地访问了
git grep
的输出,但是看看代码,它看到的是传递的参数。在视频中,他还说“所以每当我输入‘vim’”,并暗示他只是输入了没有参数的
vim
,但再次看代码,情况并非如此。我认为它赢得了很多掌声,因为它听起来比实际更神奇。看我在原始帖子中提供的视频的最后30秒?[link_at_correct_time]()根据他的描述,如果解决方案需要手动复制和粘贴上一个命令的输出,则没有任何意义。不到30秒,让我知道你的想法。他说:“我覆盖了vim,所以每当我输入‘vim’时,它都会说‘这是你最后一次输入‘git grep’的命令吗?你有没有得到:linenumber:’?如果有,我会将该文件打开到与你最近的grep匹配的行号!”