从shell中提取Linux中的模式(grep输出)?

时间:2014-07-20 21:54:14

标签: shell grep

Grep输出通常是这样的:

after/ftplugin/python.vim:49:  setlocal number

我是否可以使用标准的linux实用程序从此结果中提取文件名和行号?寻找一个非常好用的通用解决方案。

我可以考虑使用awk来获取第一个字符串:

输入

echo 'after/ftplugin/python.vim:49:  setlocal number' | awk 'print $1' 
'after/ftplugin/python.vim:49:'
$

预期

after/ftplugin/python.vim and 49

目标:在Vim中打开

我正在编写一个小函数,将grep输出转换为vim可以理解的东西 - 主要用于学术目的。我知道有像Ack.vim那样的想法做了类似的事情。什么是标准的轻量级工具?

编辑:grep -n "text to find" file.ext |cut -f1 -d:似乎是这样做的,如果你不介意双解析字符串。但是需要使用Sed!

4 个答案:

答案 0 :(得分:2)

如果您使用Bash,可以这样做:

IFS=: read FILE NUM __ < <(exec grep -Hn "string to find" file)
vim "+$NUM" "$FILE"

或POSIX:

IFS=: read FILE NUM __ <<EOD
$(grep -Hn "string to find" file)
EOD
vim "+$NUM" "$FILE"

样式©konsolebox:)

答案 1 :(得分:2)

这样做:

echo 'after/ftplugin/python.vim:49:  setlocal number' | awk -F: '{print $1,"and",$2}'
after/ftplugin/python.vim and 49

但在grep之前向我们提供数据。可能我们可以减少更多。无需grepawk

答案 2 :(得分:1)

这个怎么样?:

echo 'after/ftplugin/python.vim:49:  setlocal number' | cut -d: -f1-2 | sed -e 's/:/ and /'

结果:

after/ftplugin/python.vim and 49

答案 3 :(得分:1)

如果通过&#34;反向解析&#34;你的意思是你想从头开始(并且可以安全地假设文件内容不包含冒号),参数扩展使这很容易:

line='after/ftplugin/python.vim:49:  setlocal number'
name_and_lineno=${line%:*}
name=${name_and_lineno%:*}
lineno=${name_and_lineno##*:}

全部在进程中(使用shell内置功能),这比使用sed,awk等外部工具要快得多。

要将它们连接在一起,请考虑以下循环:

while read -r line; do
  ...
done < <(grep ...)

现在,要处理所有可能的文件名(包括冒号的文件名)所有可能的内容(包括带冒号的字符串),你需要一个带有GNU扩展名的grep:

while IFS='' read -u 4 -r -d '' file \
          && read -u 4 -r -d ':' lineno \
          && read -u 4 -r line; do
  vim "+$lineno" "$file"
done 4< <(grep -HnZ -e "string to find" /dev/null file)

其工作原理如下:

  • 使用grep -Z(GNU扩展名)使用NUL终止每个文件名而不是:
  • 使用IFS='' read -r -d ''读取文件名时的第一个NUL
  • 在读取行号
  • 时,使用read -r -d ':' lineno读取直到冒号
  • 读取行
  • 时读到下一个换行符
  • 重定向FD#4上的内容以避免覆盖stdin,stdout或stderr(因此vim仍能正常工作)
  • -u 4的所有调用使用read参数来处理来自FD#4的内容