5

在 shell 中,我使用以下函数创建文件列表并将其传递给 vim。

感觉不错,但是我丢失了行参考,我以正确的顺序打开文件,但是当光标从第一行开始时,我必须再次搜索文本。

~/.bashrc 上的实际功能

function vimgrep(){
   vim `grep -IR "$1" * | awk -F: '$1!=f{print ""$1"";f=$1}' | grep -v 'Test\|test'` +ls
}

function vimgrep2(){
   vim `grep -IR "$1" * | awk -F: '$1!=f{print ""$1"";f=$1}' ` +ls
}

Obs.: filelist 必须来自 shell 到 vim,然后它必须保留缓冲文件的行引用,就像 :make 捕获任何错误时的结果一样(但没有底部窗口 [:cwindow])。

编辑:好的...不是那么优雅,但我可以将搜索到的字符串作为 +/"$1" 传递给 vim,例如:

   vim `grep -IR "$1" * | awk -F: '$1!=f{print ""$1"";f=$1}' ` +/"$1"

如果脚本不使用临时文件会更好。

4

5 回答 5

1

使用带有外部 Grep 的行号

据我所知,不能使用行号选项标志一次打开多个文件,因为 Vim 只会将该标志应用于列表中的第一个文件。手册页说:

 +[num]      For the first file the cursor will be positioned on line  
             "num". If "num" is missing, the cursor will be positioned
             on the last line.

因此,您可以一次对每个文件调用一个函数,或者将函数调用放在一个循环中,该循环一次对两个位置参数(文件名和正则表达式)进行操作。前者当然更容易。例如:

vimgrep () {
    local file="$1"
    shift || return 1
    vim +$(egrep -n "$1" "$file" | cut -d: -f1) "$file"
}

# Sample function call.
vimgrep /etc/password '^www-data'
于 2012-07-27T18:54:29.297 回答
1

这里有一些功能可以为您提供您想要的功能。它将打开缓冲区中的每个文件,并将行设置为与给定正则表达式匹配的第一行。

我倾向于喜欢这样简短的描述性 bash 函数,因为 bash 在不使用大量代码块的情况下很难理解。

唯一的缺陷是它不能有效地过滤掉二进制文件。该功能的更新find_nonbinary将解决此问题。

这些是辅助函数。它们不能直接运行。

# Using print0 to handle files with weird names.
# This is just a quick placeholder.
# You can play with this to get better results.
function __find_nonbinary() {
    find -type f -print0
}

function __generate_vim_cmds() {
    xargs -0 awk -v regex="$regex" \
        '$0 ~ regex {printf "e +%s %s\n", FNR, FILENAME; nextfile}'
}

function __combine_vim_cmds() {
    declare -a vim_cmds

    while read line; do
        vim_cmds+=( " $line " )
    done

    # Force subshell to prevent IFS from being clobbered.
    (
        IFS="|"
        echo "${vim_cmds[*]}"
    )
}

这是要使用的实际功能。

function vimgrep() {
    local regex="$1"

    if [[ -z "$regex" ]]; then
        echo "Usage: $0 regex" 1>&2
        exit 1
    fi

    local vim_cmds=$(
        __find_nonbinary    |
        __generate_vim_cmds |
        __combine_vim_cmds
    )

    if [[ -z "$vim_cmds" ]]; then
        echo "No files matching $regex found." 1>&2
        exit 1
    fi

    vim -c "$vim_cmds"
}
于 2012-07-31T12:04:37.883 回答
1

cn有了这个,你可以通过, cp, cc..等在比赛之间移动:

function vimgrep(){
   vim -c "exec(\"grep $1 *\")"
}

突出显示:

function vimgrep(){
   vim -c "exec(\"grep -IR $1 *\")" -c "let @/='$1'" -c "set hls"
}
于 2012-07-30T16:36:03.010 回答
1

免责声明:我对此一无所知vim

手册页带有一个参数,例如+<line no>它将跳转到所提供文件的该行。根据这些信息,我编写了这个脚本。它依赖于如下命令行来启动 vim:

$ vim +n1 file1 +n2 file2

你也可以把它作为一个shell函数放在你的'~/.bashrc,因为它很小。

用法: vimgrep -e <search pattern> <fileglob>

搜索模式可以是任何可以理解的正则表达式grep,文件 glob 是可以理解的 shell glob bash

#!/bin/bash

# set -o xtrace # uncomment to debug

# declare variables
declare -a grepopts files

[[ $1 =~ -e$ ]] && grepopts+=("-e") && grepopts+=("$2") && shift 2

files=("${@}")

vim $(egrep -n -m1 -H "${grepopts[@]}" "${files[@]}" | \
        sed -e 's/^\(.\+\):\([0-9]\+\):.\+$/+\2 \1/')

警告::如果文件名中包含字符,此脚本将失败。

于 2012-07-30T20:51:25.923 回答
1

Vim 还附带了一个vimgrep你可以使用的命令

function vimgrep() {
    local regex="$1"

    if [[ -z "$regex" ]]; then
        echo "Usage: $0 regex" 1>&2
        exit 1
    fi

    vim -c "vimgrep /$regex/ **"
}

小心在其下有很多文件的目录中运行它。

于 2012-07-31T12:46:49.767 回答