{"action":"created","issue":{"url":"https://api.github.com/repos/elixir-lang/elixir/issues/3470","labels_url":"https://api.github.com/repos/elixir-lang/elixir/issues/3470/labels{/name}","comments_url":"https://api.github.com/repos/elixir-lang/elixir/issues/3470/comments","events_url":"https://api.github.com/repos/elixir-lang/elixir/issues/3470/events","html_url":"https://github.com/elixir-lang/elixir/issues/3470","id":94347736,"number":3470,"title":"Add convenience method to get given capture group from regex + string","user":{"login":"henrik","id":216,"avatar_url":"https://avatars.githubusercontent.com/u/216?v=3","gravatar_id":"","url":"https://api.github.com/users/henrik","html_url":"https://github.com/henrik","followers_url":"https://api.github.com/users/henrik/followers","following_url":"https://api.github.com/users/henrik/following{/other_user}","gists_url":"https://api.github.com/users/henrik/gists{/gist_id}","starred_url":"https://api.github.com/users/henrik/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/henrik/subscriptions","organizations_url":"https://api.github.com/users/henrik/orgs","repos_url":"https://api.github.com/users/henrik/repos","events_url":"https://api.github.com/users/henrik/events{/privacy}","received_events_url":"https://api.github.com/users/henrik/received_events","type":"User","site_admin":false},"labels":[],"state":"closed","locked":false,"assignee":null,"milestone":null,"comments":9,"created_at":"2015-07-10T17:03:10Z","updated_at":"2015-07-10T18:48:45Z","closed_at":"2015-07-10T18:48:13Z","body":"I do this kind of thing a lot in Ruby:\r\n\r\n``` ruby\r\n\"foo bar\"[/b(.)r/]  # => \"bar\"\r\n\"foo bar\"[/b(.)r/, 0]  # => \"bar\"\r\n\"foo bar\"[/b(.)r/, 1]  # => \"a\"\r\n```\r\n\r\nThe best I could come up with in Elixir was:\r\n\r\n``` elixir\r\nRegex.run(~r/b(.)r/, \"foo bar\") |> Enum.at(1)\r\n```\r\n\r\nI think a convenience function could be useful here: one that takes the string as a first argument for piping, that takes the capture number as an argument, and that handles non-matches gracefully.\r\n\r\nI sketched one below. Happy to make a proper PR with tests if this gets an {:ok}.\r\n\r\nNot at all sure about the name – please do suggest others.\r\n\r\n``` elixir\r\ndefmodule MyString do\r\n  def capture(string, regex, num) do\r\n    case Regex.run(regex, string) do\r\n      nil -> nil\r\n      list -> Enum.at(list, num)\r\n    end\r\n  end\r\n\r\n  def capture(string, regex), do: capture(string, regex, 0)\r\nend\r\n\r\nIO.inspect \"foo bar\" |> MyString.capture(~r/b(.)r/)\r\nIO.inspect \"foo bar\" |> MyString.capture(~r/b(.)r/, 0)\r\nIO.inspect \"foo bar\" |> MyString.capture(~r/b(.)r/, 1)\r\n```"},"comment":{"url":"https://api.github.com/repos/elixir-lang/elixir/issues/comments/120492523","html_url":"https://github.com/elixir-lang/elixir/issues/3470#issuecomment-120492523","issue_url":"https://api.github.com/repos/elixir-lang/elixir/issues/3470","id":120492523,"user":{"login":"bitwalker","id":955793,"avatar_url":"https://avatars.githubusercontent.com/u/955793?v=3","gravatar_id":"","url":"https://api.github.com/users/bitwalker","html_url":"https://github.com/bitwalker","followers_url":"https://api.github.com/users/bitwalker/followers","following_url":"https://api.github.com/users/bitwalker/following{/other_user}","gists_url":"https://api.github.com/users/bitwalker/gists{/gist_id}","starred_url":"https://api.github.com/users/bitwalker/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bitwalker/subscriptions","organizations_url":"https://api.github.com/users/bitwalker/orgs","repos_url":"https://api.github.com/users/bitwalker/repos","events_url":"https://api.github.com/users/bitwalker/events{/privacy}","received_events_url":"https://api.github.com/users/bitwalker/received_events","type":"User","site_admin":false},"created_at":"2015-07-10T18:48:45Z","updated_at":"2015-07-10T18:48:45Z","body":"@henrix I think the primary philosophical difference when it comes to the Elixir vs Ruby standard library is that Elixir gives you a lot of convenience, while attempting to reduce the overall API surface. In other words, in general you won't find very much, if any, crossover in functionality between functions in the API. In your case, you have the combination of `String.split`, i.e. `[_, num, _] = String.split(\"abc1233asdlkja@#$\", ~r/\\D+/, parts: 3)`, or `Regex.named_captures` to extract parts of a string based on a regular expression. If the standard library doesn't offer all of the convenience you want, it does offer the ability to easily build those tools for your own use, i.e.:\r\n\r\n```elixir\r\ndef capture(str, _, _) when str in [nil, \"\"], do nil\r\ndef capture(str, pattern, idx) when is_binary(str) and idx >= 0 do\r\n    captures = Regex.scan(pattern, str, capture: :all_but_first) \r\n                      |> List.flatten \r\n                      |> Enum.drop(idx)\r\n    case captures do\r\n      nil -> nil\r\n      []  -> nil\r\n      [h|_] -> h\r\n    end\r\nend\r\n```"}}