{"id":13414098,"url":"https://github.com/icza/backscanner","last_synced_at":"2025-08-25T16:10:16.107Z","repository":{"id":57480717,"uuid":"107376688","full_name":"icza/backscanner","owner":"icza","description":"A scanner similar to bufio.Scanner, but it reads and returns lines in reverse order, starting at a given position and going backward.","archived":false,"fork":false,"pushed_at":"2024-03-28T21:58:59.000Z","size":32,"stargazers_count":64,"open_issues_count":0,"forks_count":10,"subscribers_count":6,"default_branch":"master","last_synced_at":"2024-07-31T20:53:21.695Z","etag":null,"topics":["log","reverse","scanner"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/icza.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null},"funding":{"github":"icza"}},"created_at":"2017-10-18T07:59:07.000Z","updated_at":"2024-06-12T12:47:05.000Z","dependencies_parsed_at":"2024-02-21T19:26:46.750Z","dependency_job_id":null,"html_url":"https://github.com/icza/backscanner","commit_stats":{"total_commits":22,"total_committers":1,"mean_commits":22.0,"dds":0.0,"last_synced_commit":"2e60bffed4a2d03c425419efe480fe2052c45033"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/icza%2Fbackscanner","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/icza%2Fbackscanner/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/icza%2Fbackscanner/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/icza%2Fbackscanner/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/icza","download_url":"https://codeload.github.com/icza/backscanner/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":230367928,"owners_count":18215338,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["log","reverse","scanner"],"created_at":"2024-07-30T20:01:57.591Z","updated_at":"2024-12-19T03:09:55.369Z","avatar_url":"https://github.com/icza.png","language":"Go","readme":"# backscanner\n\n![Build Status](https://github.com/icza/backscanner/actions/workflows/go.yml/badge.svg)\n[![Go Reference](https://pkg.go.dev/badge/github.com/icza/backscanner.svg)](https://pkg.go.dev/github.com/icza/backscanner)\n[![Go Report Card](https://goreportcard.com/badge/github.com/icza/backscanner)](https://goreportcard.com/report/github.com/icza/backscanner)\n[![codecov](https://codecov.io/gh/icza/backscanner/branch/master/graph/badge.svg)](https://codecov.io/gh/icza/backscanner)\n\nEver needed or wondered how to efficiently search for something in a log file,\nbut starting at the end and going backward? Here's your solution.\n\nPackage `backscanner` provides a scanner similar to `bufio.Scanner`, but it reads\nand returns lines in reverse order, starting at a given position (which may be\nthe end of the input) and going backward.\n\nThis library only uses the standard library, but the test uses an external package.\nTo install this library (along with the test dependency), simply run:\n\n```shell\ngo get -t github.com/icza/backscanner\n```\n\nAdvancing and accessing lines of the input is done by calling `Scanner.Line()`,\nwhich returns the next line (previous in the source) as a `string`.\n\nFor maximum efficiency there is `Scanner.LineBytes()`. It returns the next line\nas a byte slice, which shares its backing array with the internal buffer of\n`Scanner`. This is because no copy is made from the line data; but this also\nmeans you can only inspect or search in the slice before calling `Line()` or\n`LineBytes()` again, as the content of the internal buffer–and thus slices\nreturned by `LineBytes()`–may be overwritten. If you need to retain the line\ndata, make a copy of it or use `Line()`.\n\n\nExample using it:\n```go\ninput := \"Line1\\nLine2\\nLine3\"\nscanner := backscanner.New(strings.NewReader(input), len(input))\nfor {\n\tline, pos, err := scanner.Line()\n\tif err != nil {\n\t\tfmt.Println(\"Error:\", err)\n\t\tbreak\n\t}\n\tfmt.Printf(\"Line position: %2d, line: %q\\n\", pos, line)\n}\n```\n\nOutput:\n\n```\nLine position: 12, line: \"Line3\"\nLine position:  6, line: \"Line2\"\nLine position:  0, line: \"Line1\"\nError: EOF\n```\n\nUsing it to efficiently scan a file, finding last occurrence of a string (`\"error\"`):\n```go\nfile, err := os.Open(\"mylog.txt\")\nif err != nil {\n\tpanic(err)\n}\nfileStatus, err := file.Stat()\nif err != nil {\n\tpanic(err)\n}\ndefer file.Close()\n\nscanner := backscanner.New(file, int(fileStatus.Size()))\nwhat := []byte(\"error\")\nfor {\n\tline, pos, err := scanner.LineBytes()\n\tif err != nil {\n\t\tif err == io.EOF {\n\t\t\tfmt.Printf(\"%q is not found in file.\\n\", what)\n\t\t} else {\n\t\t\tfmt.Println(\"Error:\", err)\n\t\t}\n\t\tbreak\n\t}\n\tif bytes.Contains(line, what) {\n\t\tfmt.Printf(\"Found %q at line position: %d, line: %q\\n\", what, pos, line)\n\t\tbreak\n\t}\n}\n```","funding_links":["https://github.com/sponsors/icza"],"categories":["Utilities","公用事业公司","工具库`可以提升效率的通用代码库和工具`","实用工具","工具库","Utility"],"sub_categories":["Utility/Miscellaneous","HTTP Clients","实用程序/Miscellaneous","查询语","Advanced Console UIs","Fail injection","交流"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ficza%2Fbackscanner","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ficza%2Fbackscanner","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ficza%2Fbackscanner/lists"}