{"id":13483311,"url":"https://github.com/tombenner/ru","last_synced_at":"2025-04-04T08:09:48.276Z","repository":{"id":23138580,"uuid":"26493671","full_name":"tombenner/ru","owner":"tombenner","description":"Ruby in your shell!","archived":false,"fork":false,"pushed_at":"2017-12-22T14:50:26.000Z","size":299,"stargazers_count":401,"open_issues_count":5,"forks_count":9,"subscribers_count":10,"default_branch":"master","last_synced_at":"2025-03-28T07:09:14.532Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tombenner.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"MIT-LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-11-11T16:30:50.000Z","updated_at":"2025-03-15T00:20:30.000Z","dependencies_parsed_at":"2022-07-31T07:18:01.178Z","dependency_job_id":null,"html_url":"https://github.com/tombenner/ru","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tombenner%2Fru","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tombenner%2Fru/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tombenner%2Fru/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tombenner%2Fru/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tombenner","download_url":"https://codeload.github.com/tombenner/ru/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247142074,"owners_count":20890653,"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":[],"created_at":"2024-07-31T17:01:09.952Z","updated_at":"2025-04-04T08:09:48.252Z","avatar_url":"https://github.com/tombenner.png","language":"Ruby","readme":"Ru\n=====\nRuby in your shell!\n\n\u003cimg src=\"https://raw.github.com/tombenner/ru/master/doc/logo.png\" /\u003e\n\n[\u003cimg src=\"https://secure.travis-ci.org/tombenner/ru.png\" /\u003e](http://travis-ci.org/tombenner/ru)\n\nOverview\n--------\n\nRu brings Ruby's expressiveness, cleanliness, and readability to the command line.\n\nIt lets you avoid looking up pesky options in man pages and Googling how to write a transformation in bash that would take you approximately 1s to write in Ruby.\n\nFor example, to center a file's lines, use [String#center](http://ruby-doc.org/core-2.0/String.html#method-i-center):\n\n```bash\nru 'map(:center, 80)' myfile\n```\n\nUsing traditional tools, this isn't as easy or readable:\n\n```bash\nawk 'printf \"%\" int(40+length($0)/2) \"s\\n\", $0' myfile\n```\n\nFor another example, let's compare summing the lines of a list of integers using Ru vs. a traditional approach:\n\n```bash\nru 'map(:to_i).sum' myfile\n```\n\n```bash\nawk '{s+=$1} END {print s}' myfile\n```\n\nAny method from Ruby Core and Active Support can be used. Ru also provides new methods (and modifies [#map](#map)) to make transformations easier. Here are some variations on the above example:\n\n```bash\nru 'map(:to_i, 10).sum' myfile\nru 'map(:to_i).reduce(\u0026:+)' myfile\nru 'each_line.to_i.to_a.sum' myfile\nru 'grep(/^\\d+$/).map(:to_i).sum' myfile\nru 'map { |n| n.to_i }.reduce(\u0026:+)' myfile\nru 'reduce(0) { |sum, n| sum + n.to_i }' myfile\nru 'each_line.match(/(\\d+)/)[1].to_i.to_a.sum' myfile\nru 'map { |n| n.to_i }.reduce(0) { |sum, n| sum + n }' myfile\n```\n\nSee [Examples](#examples) and [Methods](#methods) for more.\n\nInstallation\n------------\n\n```bash\ngem install ru\n```\n\nYou can now use Ruby in your shell!\n\nFor example, to sum a list of integers:\n\n```bash\n$ printf \"2\\n3\" | ru 'map(:to_i).sum'\n5\n```\n\nUsage\n-----\n\nSee [Examples](#examples) below, too!\n\nRu reads from stdin:\n\n```bash\n$ printf \"2\\n3\" | ru 'map(:to_i).sum'\n5\n$ cat myfile | ru 'map(:to_i).sum'\n5\n```\n\nOr from file(s):\n\n```bash\n$ ru 'map(:to_i).sum' myfile\n5\n$ ru 'map(:to_i).sum' myfile myfile\n10\n```\n\nYou can also run Ruby code without any input by prepending a `! `:\n\n```bash\n$ ru '! 2 + 3'\n5\n```\n\nThe code argument is run as if it has `$stdin.each_line.map(\u0026:chomp).` prepended to it. The result is converted to a string and printed. So, if you run `ru 'map(\u0026:to_i).sum'`, you can think of it as running `puts $stdin.each_line.map(\u0026:chomp).map(\u0026:to_i).sum`.\n\nIn addition to the methods provided by Ruby Core and Active Support, Ru provides other methods for performing transformations, like `each_line`, `files`, and `grep`, and it improves `map`. See [Methods](#methods) for more.\n\nExamples\n--------\n\nLet's compare the readability and conciseness of Ru relative to existing tools:\n\n#### Center lines\n\n##### ru\n```bash\nru 'map(:center, 80)' myfile\n```\n\n##### awk\n```bash\nawk 'printf \"%\" int(40+length($0)/2) \"s\\n\", $0' myfile\n```\n\n##### sed\n[Script](https://www.gnu.org/software/sed/manual/sed.html#Centering-lines)\n\n#### Sum a list of integers\n\n##### ru\n```bash\nru 'map(:to_i).sum' myfile\n```\n\n##### awk\n```bash\nawk '{s+=$1} END {print s}' myfile\n```\n\n##### paste\n```bash\npaste -s -d+ myfile | bc\n```\n\n#### Print the 5th line\n\n##### ru\n```bash\nru '[4]' myfile\n```\n\n##### sed\n```bash\nsed '5q;d' myfile\n```\n\n#### Print all lines except the first and last\n\n##### ru\n```bash\nru '[1..-2]' myfile\n```\n\n##### sed\n```bash\nsed '1d;$d' myfile\n```\n\n#### Sort an Apache access log by response time (decreasing, with time prepended)\n\n##### ru\n```bash\nru 'map { |line| [line[/(\\d+)( \".+\"){2}$/, 1].to_i, line] }.sort.reverse.map(:join, \" \")' access.log\n```\n\n##### awk\n```bash\nawk --re-interval '{ match($0, /(([^[:space:]]+|\\[[^\\]]+\\]|\"[^\"]+\")[[:space:]]+){7}/, m); print m[2], $0 }' access.log | sort -nk 1\n```\n[Source](https://coderwall.com/p/ueazhw)\n\nMethods\n-------\n\nIn addition to the methods provided by Ruby Core and Active Support, Ru provides other methods for performing transformations.\n\n#### each_line\n\nProvides a shorthand for calling methods on each iteration of the input. Best explained by example:\n\n```bash\nru 'each_line.strip.center(80)' myfile\n```\n\nIf you'd like to transform it back into a list, call `to_a`:\n\n```bash\nru 'each_line.strip.to_a.map(:center, 80)' myfile\n```\n\n#### files\n\nConverts the lines to `Ru::File` objects (see Ru::File below).\n\n```bash\n$ printf \"foo.txt\" | ru 'files.map(:updated_at).map(:strftime, \"\"%Y-%m-%d\")'\n2014-11-08\n```\n\n#### format(format='l')\n\nFormats a list of `Ru::File`s. You'll typically call this after calling `files` to transform them into strings:\n\n```bash\n$ ru 'files.format'\n644\ttom\tstaff\t3\t2014-10-26\t09:06\tbar.txt\n644\ttom\tstaff\t11\t2014-11-04\t08:29\tfoo.txt\n```\n\nThe default format, `'l'`, is shown above. It prints `[omode, owner, group, size, date, name]`.\n\n#### grep\n\nSelects lines which match the given regex.\n\n```bash\n$ printf \"john\\npaul\\ngeorge\" | ru 'grep(/o[h|r]/)'\njohn\ngeorge\n```\n\n#### map\n\nThis is the same as [Array#map](http://www.ruby-doc.org/core-2.0/Array.html#method-i-map), but it adds a new syntax that allows you to easily pass arguments to a method. For example:\n\n```bash\n$ printf \"john\\npaul\" | ru 'map(:[], 0)'\nj\np\n$ printf \"john\\npaul\" | ru 'map(:center, 8, \".\")'\n..john..\n..paul..\n```\n\nNote that the examples above can also be performed with `each_line`:\n\n```bash\n$ printf \"john\\npaul\" | ru 'each_line[0]'\n$ printf \"john\\npaul\" | ru 'each_line.center(8, \".\")'\n```\n\nRu::File\n------------\n\nThe [`files`](#files) method returns an enumerable of `Ru::File`s, which are similar to Ruby Core's [`File`](http://ruby-doc.org/core-2.0/File.html). Each one has the following methods:\n\n* `basename`\n* `created_at` (alias for ctime)\n* `ctime`\n* `extname`\n* `format` (see the [`format`](#formatformatl) method above)\n* `ftype`\n* `gid`\n* `group`\n* `mode`\n* `mtime`\n* `name` (alias for basename)\n* `omode`\n* `owner`\n* `size`\n* `to_s` (alias for name)\n* `uid`\n* `updated_at` (alias for mtime)\n* `world_readable?`\n\nSaved Commands\n--------------\n\nRu lets you save commands by name, so that you can easily use them later.\n\n#### save\n\nSave a command for future use:\n\n```bash\n$ ru save sum 'map(:to_i).sum'\nSaved command: sum is 'map(:to_i).sum'\n```\n\n#### run\n\nRun a saved command:\n\n```bash\n$ printf \"2\\n3\" | ru run sum\n5\n$ ru run sum myfile\n5\n```\n\n#### list\n\nList all of your saved commands:\n\n```bash\n$ ru list\nSaved commands:\nsum\tmap(:to_i).sum\n```\n\nOptions\n-------\n\n#### -h, --help\n\nPrint a help page.\n\n#### -v, --version\n\nPrint the installed version of Ru.\n\nTesting\n-------\n\nRu is tested against Active Support 3 and 4. If you'd like to submit a PR, please be sure to use [Appraisal](https://github.com/thoughtbot/appraisal) to test your changes in both contexts:\n\n```bash\nappraisal rspec\n```\n\nLicense\n-------\n\nRu is released under the MIT License. Please see the MIT-LICENSE file for details.\n","funding_links":[],"categories":["CLI Utilities","Ruby","CLI Builder"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftombenner%2Fru","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftombenner%2Fru","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftombenner%2Fru/lists"}