Stringモジュールで遊んでみたシリーズ⑦ -String.replace_trailing ~ String.split の紹介

こんにちは！
プログラミング未経験文系出身、Elixirの国に迷い込んだ？！見習いアルケミストのaliceと申します。
今回はStringモジュールについて学んだことをまとめます。


# 目次
1.[Stringモジュールで遊んでみたシリーズ① -String.at ~ String.chunk の紹介](https://qiita.com/Alicesky2127/items/47fffc38711d7369beee)
2.[Stringモジュールで遊んでみたシリーズ② -String.codepoints ~ String.ends_with? の紹介](https://qiita.com/Alicesky2127/items/5db34c69993d35b8f3a7)
3.[Stringモジュールで遊んでみたシリーズ③ -String.equivalent? ~ String.last の紹介](https://qiita.com/Alicesky2127/items/37aa8e62e8e1d5fef3b6)
4.[Stringモジュールで遊んでみたシリーズ④ -String.length ~ String.next_grapheme の紹介](https://qiita.com/Alicesky2127/items/e3fa2092a67cb9f6ec9c)
5.[Stringモジュールで遊んでみたシリーズ⑤ -String.next_grapheme_size ~ String.printable? の紹介](https://qiita.com/Alicesky2127/items/a315148e966c9f103a7c)
6.[Stringモジュールで遊んでみたシリーズ⑥ -String.replace ~ String.replace_suffix の紹介](https://qiita.com/Alicesky2127/items/94a77afe270587ed21a9)
7.Stringモジュールで遊んでみたシリーズ⑦ -String.replace_trailing ~ String.split の紹介(本記事)
8.[Stringモジュールで遊んでみたシリーズ⑧ -String.split_at ~ String.to_charlist の紹介](https://qiita.com/Alicesky2127/items/40e74cd622653796df5c)
9.[Stringモジュールで遊んでみたシリーズ⑨ -String.to_existing_atom ~ String.trim の紹介](https://qiita.com/Alicesky2127/items/9bf2b1effc3b68819ac2)
10.[Stringモジュールで遊んでみたシリーズ10 -String.trim_leading ~ String.valid? の紹介](https://qiita.com/Alicesky2127/items/b8310a3f5fc5b040ca78)

# 目的 
Stringモジュールに含まれる関数を触って機能を理解したい

https://hexdocs.pm/elixir/String.html

## 実行環境
Windows 11 ＋ WSL2 ＋ Ubuntu 22.04
Elixir v1.17.3
Erlang v27.0


# String.replace_trailingとは
`String.replace_trailing(string, match, replacement)`は`string`内の後方一致検索を行い、`match`にヒットした部分を`replacement`に置き換えます。

## 例
```diff_elixir:iex
String.replace_trailing("hello world", " world", "")
```
```
"hello"
```

後方一致検索なので末尾にヒットしなければ置換されません
```diff_elixir:iex
String.replace_trailing("hello world thanks", " world", "")
```
```
"hello world thanks"
```

`subject`の末尾から`match`にヒットする要素が2回連続する場合全て置換されます
```diff_elixir:iex
String.replace_trailing("hello world world", " world", "")
```
```
"hello"
```

# 文字列を置換するString関数のまとめ
文字列を置換するString関数の差分をまとめると下記の表の通りです

| 関数名 | 検索方法 | 連続ヒット時 |
|:---------|:------:|:------:|
| replace     | 部分一致     | 全て置換      |
| replace_leading     | 前方一致     | 全て置換      |
| replace_prefix    | 前方一致     | 最初にヒットした部分のみ置換      |
| replace_suffix    | 後方一致     | 最初にヒットした部分のみ置換      |
| replace_trailing    | 後方一致     | 全て置換      |

1つ前の記事もご参照ください

https://qiita.com/Alicesky2127/items/94a77afe270587ed21a9



# String.reverseとは
`String.reverse(string)`は`string`を逆順にして返します

## 例
```diff_elixir:iex
String.reverse("abcd")
```
```
"dcba"
```

```diff_elixir:iex
String.reverse("いろはにほへと ちりぬるを")
```
```
"をるぬりち とへほにはろい"
```

# String.sliceとは(slice/2)
`String.slice(string, range)`は`string`から`range`ぶんの部分文字列を返します。

## 例
```diff_elixir:iex
String.slice("elixir", 0..2)
```
```
"eli"
```

`range`が`string`の末尾を超える場合。
`string`の末尾までを取り出します
```diff_elixir:iex
String.slice("elixir", 1..10)
```
```
"lixir"
```

`range`が負の数の場合
`string`の末尾からインデックスを数えます
```diff_elixir:iex
String.slice("elixir", -4..-3)
```
```
"ix"
```

### `range`を`start..stop`としたとき
`range`を`start..stop`としたとき、`start > stop`の範囲の場合ではステップ数ごとに文字を取り出します。
ステップ数を`//`で書かないとwarningが出ます
```diff_elixir:iex
String.slice("いろはにほへと", 1..-2//1) 
# インデックスが1(この場合"ろ")をstartとする
# インデックスが-1(この場合"へ")をendとする
# //1なのでステップ数が1。つまり1文字ごとに取り出す
```
```
"ろはにほへ"
```

ステップ数を変更した場合
```diff_elixir:iex
String.slice("いろはにほへと", 1..-2//2)
# インデックスが1(この場合"ろ")をstartとする
# インデックスが-1(この場合"へ")をendとする
# //1なのでステップ数が2。つまり2文字ごとに取り出す
```
```
"ろにへ"
```




# String.sliceとは(slice/3)
`String.slice(string, start, length)`は書記素ベースで`start`から`length`ぶんの部分文字列を返します。

※書記素ベースではなくバイト数ベースで取り出したい場合は`String.byte_slice`を使用のこと↓

https://qiita.com/Alicesky2127/items/47fffc38711d7369beee#stringbyte_slice%E3%81%A8%E3%81%AF

## 例
```diff_elixir:iex
String.slice("elixir", 1, 3)
```
```
"lix"
```

取り出す範囲が`string`の末尾を超える場合。
`start`から`string`の末尾までを取り出します
```diff_elixir:iex
String.slice("elixir", 1, 10)
```
```
"lixir"
```

`start`が文字列の長さより大きい場合。
空の文字列を返します
```diff_elixir:iex
String.slice("elixir", 10, 1)
```
```
""
```

`start`が負の数の場合。
`string`の末尾からインデックスを数えます
```diff_elixir:iex
String.slice("elixir", -2, 1)
```
```
"i"
```

```diff_elixir:iex
String.slice("elixir", -2, 3)
```
```
"ir"
```

`start`が負の数かつ文字列の長さより大きい場合。
`start = 0`の時と同様の扱いになります

```diff_elixir:iex
String.slice("elixir", -10, 1)
```
```
"e"
```



# String.splitとは(split/1)
下記をご参照ください

https://qiita.com/Alicesky2127/items/400e6c928b791609b6d5#stringsplit1


# String.splitとは(split/3)
下記をご参照ください

https://qiita.com/Alicesky2127/items/400e6c928b791609b6d5#stringsplit3





# ～Elixirの国のご案内～
↓Elixirって何ぞや？と思ったらこちらもどぞ。Elixirは先端のアレコレをだいたい全部できちゃいます:laughing::sparkles::sparkles:

https://qiita.com/piacerex/items/09876caa1e17169ec5e1

↓ゼロからElixirを始めるなら「エリクサーチ」がおすすめ！私もエンジニア未経験から学習中です。

https://elixir-lang.info/topics/entry_column


↓[We Are The Alchemists, my friends!:bouquet:](https://qiita.com/torifukukaiou/items/6bcd5bbb80df9e594e9e "Awesome-san's Awesome article")[^10]
Elixirコミュニティは本当に優しくて温かい人たちばかり！
私が挫折せずにいられるのもこの恵まれた環境のおかげです。
まずは気軽にコミュニティを訪れてみてください。[^11]


https://speakerdeck.com/elijo/elixirkomiyunitei-falsebu-kifang-guo-nei-onrainbian




[^10]: @torifukukaiouさんのAwesomeな名言をお借りしました。Elixirコミュニティを一言で表すと、これに尽きます。


[^11]: @kn339264さんの素敵なスライドをお借りしました。Elixirコミュニティはいろんな形で活動中！