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