我编写了一个函数,可以在Python文件中找到函数或类定义。它生成一个与vim一起使用的参数列表。它适用于第一个参数/文件,但后续文件失败,因为尾随“被添加到文件名。
尽管生成了正确的输出,但是当传递给vim时它不起作用。但是,当在命令行复制并粘贴相同的输出时,它可以工作。问题是,当它应该是命令字符串的结束时,结束"
将被解析为文件名的一部分:
vim +cmd1 file1 +"file2_cmd file2_cmd file2" +"file3_cmd file3_cmd file3"
我需要在添加命令时添加文字双引号(\"
)的函数,但在与vim一起使用时解析文字引号。奇怪的是第一个文字引用被解析但不是最终文字引用。
vim +cmd file1 +" <-- this quote works, but this one doesn't --> "
代码:
function vpfd {
local args=''
find . -name "*.py" \
| xargs grep -En "(def|class) ${@}[(:]" \
| uniq \
| while read line; do
name=$(echo "${line}" | awk 'BEGIN { FS=":" }; { print $1 }')
num=$(echo "${line}" | awk 'BEGIN { FS=":" }; { print $2 }')
if [ ! "${args}" ]; then
args="+${num} ${name}"
else
args+=" +\"tabnew +${num} ${name}\""
fi
done
if [ "${args}" ]; then
echo "vim ${args}"
read p
vim $(echo ${args})
fi
示例:
$ vpfd main
vim +33 ./bar.py +"tabnew +15 ./foo.py"
如果我复制并粘贴上面一行就可以了,但是当函数试图打开vim并将其传递给${args}
时,它不起作用。
在vim中:
Vim: not an editor command: 33 ./bar.py +"tabnew +15 ./foo.py"
./bar.py
,在第二个标签上打开错误的文件./foo.py"
(尾随"
)如果我复制并粘贴输出行,那么它可以正常工作:
$ vim +33 ./bar.py +"tabnew +15 ./foo.py"
答案 0 :(得分:1)
这就是你需要的:
function vpfd {
local args=() name num
# in bash, putting a while loop in a pipeline implies the loop
# runs in a subshell, thus when the subshell exits you will lose
# any variable modifications.
# Have the while loop read from a process substitution instead.
# The read command can store multiple values, given the appropriate
# field separator
while IFS=: read -r name num; do
if (( ${#args[@]} == 0 )); then
args=( "+$num" "$name" )
else
args+=( +"tabnew +$num $name")
fi
done < <(
find . -name "*.py" |
xargs grep -En "(def|class) ${@}[(:]" |
uniq
)
if (( ${#args[@]} > 0 )); then
echo "${args[*]}"
read -p "hit enter to continue" x
vim "${args[@]}"
fi
}
表单"${array[@]}"
(带有@
和双引号)会将数组扩展为其元素列表。
表单"${array[*]}"
会将数组扩展为单个字符串。
答案 1 :(得分:0)
你遇到的第一个问题是args不会在while循环之外更新。因此,不应在查找中使用管道,而应使用重定向。
while read line; do
name=$(echo "${line}" | awk 'BEGIN { FS=":" }; { print $1 }')
num=$(echo "${line}" | awk 'BEGIN { FS=":" }; { print $2 }')
if [ ! "${args}" ]; then
args="+${num} ${name}"
else
args+=" +\"tabnew +${num} ${name}\""
fi
done < <(find . -name "*.py" | xargs grep -En "(def|class) ${@}[(:]" | uniq)
这允许args变量在while循环之外更新。
(这对您来说似乎不是问题,但我无法在不更改此情况的情况下使您的脚本正常工作)
可以通过更改行
来修复字符串中引号过多的下一个问题args+=" +\"tabnew +${num} ${name}\""
要
args+=" +\"tabnew +${num} ${name}"
但我不确定这是一个强有力的解决方案。
修改更强大的解决方案是Ignacio Vazquex-Abrams Answer,除非在适当的位置加上引号。
您将遇到的最后一个问题是vim只接受十个+
命令。因此,请确保您的脚本说明了这一点。