在一个字符串中查找文件路径

huangapple go评论75阅读模式
英文:

Finding file paths in a string

问题

我修改了gnome-terminal并添加了对自定义URL处理程序的支持:src://。当你ctrl-click时,它可以让你直接跳转到文件中的行号。

例如src:///path/to/file:43

这一切都很好,但现在我需要一种过滤器,将所有相对路径和绝对路径转换为绝对的src链接。然后我就可以通过它将另一个程序的输出导入。

例如

$ go build

# command-line-arguments
./test.go:3931: undefined: erre

我想要这样的效果

$ go build | src-links

# command-line-arguments
src:///home/icholy/gocode/src/test/test.go:3931: undefined: erre

我最初的想法是使用正则表达式,但我找到的唯一示例都是已经带有方案/协议前缀的路径。

我被卡住了,所以非常希望能得到一些想法/建议。我将在go中实现它,但这并不重要。

英文:

I modified gnome-terminal and added support for a custom url handler: src://
It lets you jump directly to line number in a file when you ctrl-click.

example src:///path/to/file:43

This is all good, but now I need some type of filter which converts all relative and absolute paths to absolute src links. Then I'd be able to pipe another programs output through it.

example

$ go build

# command-line-arguments
./test.go:3931: undefined: erre

I want something like this

$ go build | src-links

# command-line-arguments
src:///home/icholy/gocode/src/test/test.go:3931: undefined: erre

My first thought was to use a regex, but the only examples I found were paths already prefixed with a scheme/prototcol.

I'm stuck, so ideas/suggestions would be greatly appreciated. I'll be implementing it in go, but that's of little importance.

答案1

得分: 2

非常酷的想法。但是文件名有一个相当通用的格式,所以我认为你只需要覆盖其中的一部分,而不是全部。

如果你打算将其用于编程工作,那么你可能认为只匹配许多程序员认为是良好实践的文件名是可以接受的。也就是说,路径中的字符集与[A-Za-z0-9/_.-]匹配。你还期望你要查找的是一个文件名后跟着':\d+',并且行规范与其他看起来可能是行规范的字符不连续。最后一部分可以通过前后环视断言来完成。

如果你将其与文件存在性测试(相对于当前目录或指定目录)结合起来,那么你就有了一个相当可管理的范围和一个健壮的测试。

所以你的文件规范正则表达式大致是这样的:

(?<![A-Za-z0-9/_.-])([A-Za-z0-9_.-]):(\d+)(?![A-Za-z0-9/_.-])

你应该能够通过将它们附加到所需路径来将大多数这样的文件规范转换为绝对格式,除非它们以'/'开头。

$PATH/$file_path

路径以'./'开头并不重要。上述方法仍然有效,因为'/foo/./bar/baz'是一个可接受的路径。同样适用于'/foo/bar/../../bar/baz/xyz'。

你应该确保你在这里使用的规范与你的gnome终端认为是链接的一部分相吻合。

关于你如何处理gnome终端的细节,很高兴能看到。这将使这个页面对其他人在将来更有用。

英文:

Very cool idea. File names however have a fairly general format, so I suspect you should only aim to cover a significant fraction of them, not all.

If you intend using this for programming work, then you might consider it acceptable to only match the sort of file names that many programmers consider good practice. ie the character set in the paths matches [A-Za-z0-9/_.-] . You also expect that what you are looking for is a filename followed by ':\d+', and that the line spec is not contiguous with other characters that look like they might be part of a line spec. That last bit can be done with forward and backward look-around assertions.

If you combine that with tests for file existence (relative to current or a specified directory), then you've got a pretty manageable scope, and a robust test.

So your file spec regex is something like this:

(?&lt;![A-Za-z0-9/_.-])([A-Za-z0-9_.-]):(\d+)(?![A-Za-z0-9/_.-])

You should be able to convert most such file specs to absolute format by just appending them to the desired path, unless they start with a /.

$PATH/$file_path

It doesn't matter if the path starts with ./. The above works anyway, since /foo/./bar/baz is an acceptable path. Same with /foo/bar/../../bar/baz/xyz&#39;\.

You should try to be sure that the spec you use here lines up with what your gnome terminal considers as part of the link.

Details on how you did the gnome terminal bit would be nice to see. It'd make this page more useful to others in future.

答案2

得分: 1

除了mc0e提供的正则表达式解决方案之外,一旦找到带有文件名的字符串,您可以通过类似以下的管道将它们传递给某个东西:

package main

import (
	"bufio"
	"fmt"
	"os"
	"path/filepath"
)

func checkLine(s string) bool {
	// 在这里插入正则表达式检查逻辑。现在只检查空行。
	if s == "" {
		return false
	}
	return true
}

func srcerer(s string) (string, error) {
	p, err := filepath.Abs(s)
	if err != nil {
		return "", err
	}
	return "src:///" + p, nil
}

func main() {
	scanner := bufio.NewScanner(os.Stdin)
	for scanner.Scan() {
		v := scanner.Text()
		if checkLine(v) {
			link, err := srcerer(v)
			if err != nil {
		        fmt.Fprintln(os.Stderr, "Error:", err)
				return
			}
			fmt.Println(link)
		}
	}
	if err := scanner.Err(); err != nil {
		fmt.Fprintln(os.Stderr, "reading standard input:", err)
	}
	return
}

将上述代码编译为名为src-links的二进制文件,并给定一个名为testlines.txt的文件,其中包含以下内容:

./test.go:14: undefined: erre
./test.go:16: undefined: erre
./test.go:21: undefined: erre
./test.go:27: undefined: erre

命令cat testlines.txt | src-links将输出:

src:///home/icholy/gocode/src/test/test.go:14: undefined: erre
src:///home/icholy/gocode/src/test/test.go:16: undefined: erre
src:///home/icholy/gocode/src/test/test.go:21: undefined: erre
src:///home/icholy/gocode/src/test/test.go:27: undefined: erre
英文:

In addition to the regexp solution provided by mc0e, once you've found the strings with file names, you can pipe them through something like:

package main

import (
	&quot;bufio&quot;
	&quot;fmt&quot;
	&quot;os&quot;
	&quot;path/filepath&quot;
)

func checkLine(s string) bool {
	// Insert regex checking logic here. Just checking for blank line now.
	if s == &quot;&quot; {
		return false
	}
	return true
}

func srcerer(s string) (string, error) {
	p, err := filepath.Abs(s)
	if err != nil {
		return &quot;&quot;, err
	}
	return &quot;src:///&quot; + p, nil
}

func main() {
	scanner := bufio.NewScanner(os.Stdin)
	for scanner.Scan() {
		v := scanner.Text()
		if checkLine(v) {
			link, err := srcerer(v)
			if err != nil {
		        fmt.Fprintln(os.Stderr, &quot;Error:&quot;, err)
				return
			}
			fmt.Println(link)
		}
	}
	if err := scanner.Err(); err != nil {
		fmt.Fprintln(os.Stderr, &quot;reading standard input:&quot;, err)
	}
	return
}

Which, compiling the above code to a binary called src-links, and given a file called testlines.txt with the contents:

./test.go:14: undefined: erre
./test.go:16: undefined: erre
./test.go:21: undefined: erre
./test.go:27: undefined: erre

the command cat testlines.txt | src-links would output:

src:///home/icholy/gocode/src/test/test.go:14: undefined: erre
src:///home/icholy/gocode/src/test/test.go:16: undefined: erre
src:///home/icholy/gocode/src/test/test.go:21: undefined: erre
src:///home/icholy/gocode/src/test/test.go:27: undefined: erre

huangapple
  • 本文由 发表于 2013年6月8日 00:49:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/16989204.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定