VBAユーザがPython・Rを使ってみた：文字列操作

# はじめに

機械学習の勉強を始めたVBAユーザです。
備忘録としてPython・Rの文法をVBAと比較しながらまとめていきたいと思います。


**目次**

* [文字列操作](#文字列操作)
  + [文字列の結合](#文字列の結合)
  + [文字列の長さ](#文字列の長さ)
  + [文字列の取り出し](#文字列の取り出し)
  + [文字列の検索](#文字列の検索)
  + [文字列の置換](#文字列の置換)
  + [文字列の変換](#文字列の変換)
     - [大文字と小文字の変換](#大文字と小文字の変換)
     - [全角と半角の変換](#全角と半角の変換)
  + [文字列の反転](#文字列の反転)
  + [文字列の繰り返し](#文字列の繰り返し)
  + [スペース](#スペース)
     - [スペースの文字列](#スペースの文字列) 
     - [前後の不要なスペースの削除](#前後の不要なスペースの削除)
  + [アスキーコード](#アスキーコード)
* [まとめ](#まとめ)
  - [一覧](#一覧)
  - [プログラム全体](#プログラム全体)


# 文字列操作
PythonとRの文字列操作について、VBAと比較しながらまとめます。
Rの`stringr`パッケージを使った文字列操作については[こちら](https://qiita.com/swathci/items/e26bd7fa7eadf0842caa)。


## 文字列の結合

**Python**

```Python:Python3
s1 = 'abc'
s2 = 'def'
s3 = 'ghij'
print(s1 + s2 + s3)
# abcdefghij
```
Pythonでは算術演算と同じ`+`演算子を使います。ちなみに`*`演算子は文字列の繰り返しに使います（後述）。

**R**

```R:R
s1 <- "abc"
s2 <- "def"
s3 <- "ghij"
paste0(s1, s2, s3)
# "abcdefghij"
paste(s1, s2, s3)
# "abc def ghij"
paste(s1, s2, s3, sep="")
# "abcdefghij"
```
Rの`paste`関数はデフォルトでスペースが入ります。

**VBA**

```VBA:VBA
s1 = "abc"
s2 = "def"
s3 = "ghij"
Debug.Print s1 & s2 & s3
' abcdefghij
```


## 文字列の長さ

**Python**

```Python:Python3
s = 'abcdefghij'
print(len(s))
# 10
```

**R**

```R:R
s <- "abcdefghij"
nchar(s)
# 10
length(s)
# 1
```
Rの`length`関数は文字列の長さではなく、文字列ベクトルの要素数を返します。

**VBA**

```VBA:VBA
s = "abcdefghij"
Debug.Print Len(s)
' 10
```


## 文字列の取り出し

**Python**

```Python:Python3
s = 'abcdefghij'
print(s[0:2])
print(s[:2])
# ab
print(s[8:10])
print(s[len(s)-2:len(s)])
print(s[-2:])
# ij
print(s[3:6])
# def
```
Pythonでは、文字列から部分文字列を取り出すのに、スライス表記を使います。エクセルのLEFT、RIGHTのような関数はないようです。
スライスについての説明は、[公式チュートリアル](https://docs.python.org/ja/3/tutorial/introduction.html#strings)のこの説明がわかりやすいです。
> スライスの使い方をおぼえる良い方法は、インデックスが文字と文字の あいだ (between) を指しており、最初の文字の左端が 0 になっていると考えることです。そうすると、 *n* 文字からなる文字列中の最後の文字の右端はインデックス *n* となります。例えばこうです:
>
```
 +---+---+---+---+---+---+
 | P | y | t | h | o | n |
 +---+---+---+---+---+---+
 0   1   2   3   4   5   6
-6  -5  -4  -3  -2  -1
```
> 1行目の数字は文字列の 0 から 6 までのインデックスの位置を示しています; 2行目は対応する負のインデックスを示しています。*i* から *j* までのスライスは、それぞれ *i* と付いた境界から *j* と付いた境界までの全ての文字から成っています。

**R**

```R:R
s <- "abcdefghij"
substr(s, 1, 2)
# "ab"
substring(s, 1, 2)   # substrとほぼ同じ
# "ab"
substr(s, nchar(s)-2+1, nchar(s))
# "ij"
substr(s, 4, 6)
# "def"
```

**VBA**

```VBA:VBA
s = "abcdefghij"
Debug.Print Left(s, 2)
' ab
Debug.Print Right(s, 2)
' ij
Debug.Print Mid(s, 4, 3)
' def
```

## 文字列の検索

**Python**

```Python:Python3
s = 'abcdefghij'
print(s.find('def'))
# 3
t = s + s # 'abcdefghijabcdefghij'
print(t.rfind('def'))
# 13
print(t.count('def'))
# 2
print('def' in t)
# True
print('def' not in t)
# False
```

**R**

```R:R
s <- "abcdefghij"
match("def", s) #完全一致
# NA
"def" %in% s    #完全一致
# FALSE
grep("def", s)  #部分一致（パターンマッチ）
# 1
# これはsという文字列ベクトルの1番目の要素(いまは要素は1つしかないが)に部分一致があったということ（1文字目ということではない）
regexpr("def", s)
# [1] 4
# attr(,"match.length")
# [1] 3
# attr(,"index.type")
# [1] "chars"
# attr(,"useBytes")
# [1] TRUE
regexpr("def", s)[1]
# [1] 4
t <- paste(s, s, sep="")
t
# [1] "abcdefghijabcdefghij"
gregexpr("def", t)
# [[1]]
# [1]  4 14
# attr(,"match.length")
# [1] 3 3
# attr(,"index.type")
# [1] "chars"
# attr(,"useBytes")
# [1] TRUE
```

**VBA**

```VBA:VBA
s = "abcdefghij"
Debug.Print InStr(1, s, "def")
' 4
Debug.Print InStr(1, s, "DEF")
' 0
t = s & s ' abcdefghijabcdefghij
Debug.Print InStrRev(t, "def") '後ろから検索
' 14
```

## 文字列の置換

**Python**

```Python:Python3
s = 'abcdefghij'
print(s.replace('def', 'DEF'))
# 'abcDEFghij'
t = s + s # 'abcdefghijabcdefghij'
print(t.replace('def', 'DEF'))
# 'abcDEFghijabcDEFghij'
```

**R**

```R:R
s <- "abcdefghij"
sub("def", "DEF", s)
# "abcDEFghij"
t <- paste(s, s, sep="") # "abcdefghijabcdefghij"
sub("def", "DEF", t)  # 最初の1つだけ置換
# "abcDEFghijabcdefghij"
gsub("def", "DEF", t) # すべて置換
# "abcDEFghijabcDEFghij"
```

**VBA**

```VBA:VBA
s = "abcdefghij"
Debug.Print Replace(s, "def", "DEF")
' abcDEFghij
t = s & s ' abcdefghijabcdefghij
Debug.Print Replace(t, "def", "DEF")
' abcDEFghijabcDEFghij
```


## 文字列の変換

### 大文字と小文字の変換

**Python**

```Python:Python3
s = 'abcDEFghij'
print(s.upper())      # 大文字に
# ABCDEFGHIJ
print(s.lower())      # 小文字に
# abcdefghij
print(s.capitalize()) # 先頭のみ大文字・それ以外は小文字に
# Abcdefghij
print(s.swapcase())   # 大文字と小文字を入れ替え
# ABCdefGHIJ
print(s.isupper(), s.islower(), s.upper().isupper(), s.lower().islower())
# False False True True
```

**R**

```R:R
s <- "abcDEFghij"
toupper(s)              # 大文字に
chartr("a-z", "A-Z", s) # 大文字に
# "ABCDEFGHIJ"
tolower(s)              # 小文字に
chartr("A-Z", "a-z", s) # 小文字に
# "abcdefghij"
paste0(substr(toupper(s),1,1), substr(tolower(s),2,nchar(s))) # 先頭のみ大文字・それ以外は小文字に
# "Abcdefghij"
chartr("A-Za-z", "a-zA-z", s)  #大文字・小文字を入れ替え
# "ABCdefGHIJ"
s == toupper(s)  #すべて大文字かどうかの判定
# FALSE
s == tolower(s)  #すべて小文字かどうかの判定
# FALSE
```

**VBA**

```VBA:VBA
s = "abcDEFghij"
Debug.Print UCase(s)                 ' 大文字に
Debug.Print StrConv(s, vbUpperCase)  ' 大文字に
' ABCDEFGHIJ
Debug.Print LCase(s)                 ' 小文字に
Debug.Print StrConv(s, vbLowerCase)  ' 小文字に
' abcdefghij
Debug.Print UCase(Left(s, 1)) & Right(LCase(s), Len(s) - 1) ' 先頭のみ大文字・それ以外は小文字に
Debug.Print StrConv(s, vbProperCase) ' 先頭のみ大文字・それ以外は小文字に
' Abcdefghij
```

### 全角と半角の変換

**Python**

```Python:Python3
```
Pythonには全角・半角を変換する組み込み関数はなさそうです。

**R**

```R:R
s <- "abcDEFghij"
chartr("A-Za-z", "Ａ-Ｚａ-ｚ", s)  # 半角を全角に
# "ａｂｃＤＥＦｇｈｉｊ"
chartr("Ａ-Ｚａ-ｚ", "A-Za-z", chartr("A-Za-z", "Ａ-Ｚａ-ｚ", s))  # 全角を半角に
# "abcDEFghij"
```

**VBA**

```VBA:VBA
' Abcdefghij
s = "abcDEFghij"
Debug.Print StrConv(s, vbWide)                    ' 全角へ
' ａｂｃＤＥＦｇｈｉｊ
Debug.Print StrConv(StrConv(s, vbWide), vbNarrow) ' 半角へ
' abcDEFghij
```

## 文字列の反転

**Python**

```Python:Python3
s = 'abcdefghij'
print(s[::-1])
# jihgFEDcba
t = ''
for i in range(len(s)):
    t = t + s[len(s)-i-1]
print(t)
```
Pythonでは、リストのスライス表記を使って文字列の反転ができます。

**R**

```R:R
s <- "abcdefghij"
t <- ""
for (i in 1:nchar(s)) {
  t <- paste0(t, substr(s, nchar(s)-i+1, nchar(s)-i+1))
}
t
# "jihgfedcba"
```

**VBA**

```VBA:VBA
s = "abcdefghij"
Debug.Print StrReverse(s)
' jihgfedcba
```
VBAには文字列を反転させる関数があります。


## 文字列の繰り返し

**Python**

```Python:Python3
print('A' * 3)
# AAA
print('def' * 3)
# defdefdef
```
Pythonでは文字列に算術演算子`*`を使って文字列を繰り返すことができます。

**R**

```R:R
rep("A", 3)
# "A" "A" "A"
paste(rep("A", 3), collapse="")
# "AAA"
paste(rep("def", 3), collapse="")
# "defdefdef"
```
まず、`rep("A", 3)`で"A"という文字列を要素とする長さ3の文字列ベクトルを作成します。その各要素を`paste`関数で結合しているだけです。

**VBA**

```VBA:VBA
Debug.Print String(3, "A")
' AAA
Debug.Print String(3, "def")
' ddd
Dim i As Integer
s = ""
For i = 1 To 3
    s = s & "def"
Next i
Debug.Print s
' defdefdef
```
`String(3, "def")`は"defdefdef"とはなりません。


## スペース
### スペースの文字列
**Python**

```Python:Python3
s = ' ' * 3
print('-' + s + '-')
# -   -
s = ' '*2 + 'd' + ' '*3 + 'e' + ' '*4 + 'f' + ' '*5
print('-' + s + '-')
# -  d   e    f     -
```

**R**

```R:R
s <- paste(rep(" ", 3), collapse="")
paste("-", s, "-", sep="")
# "-   -"
s <- paste("-",
           paste(rep(" ", 2), collapse=""), 
           "d", 
           paste(rep(" ", 3), collapse=""),
           "e",
           paste(rep(" ", 4), collapse=""),
           "f",
           paste(rep(" ", 5), collapse=""),
           "-",
           sep="")
s
# "-  d   e    f     -"
```

**VBA**

```VBA:VBA
s = Space(3)
Debug.Print "-" & s & "-"
' -   -
s = Space(2) & "d" & Space(3) & "e" & Space(4) & "f" & Space(5)
Debug.Print "-" & s & "-"
' -  d   e    f     -
```

### 前後の不要なスペースの削除

**Python**

```Python:Python3
s = ' '*2 + 'd' + ' '*3 + 'e' + ' '*4 + 'f' + ' '*5
print(s.strip(' '))
# 'd   e    f'
print(s.lstrip(' '))
# 'd   e    f     '
print(s.rstrip(' '))
# '  d   e    f'
```

**R**

```R:R
```
Rにはトリム関数がないようです。

**VBA**

```VBA:VBA
s = Space(2) & "d" & Space(3) & "e" & Space(4) & "f" & Space(5)
Debug.Print "-" & Trim(s) & "-"
' -d   e    f-
Debug.Print "-" & LTrim(s) & "-"
' -d   e    f     -
Debug.Print "-" & RTrim(s) & "-"
' -  d   e    f-
```


## アスキーコード
最後は、文字のアスキー(ASCII)コードです。

**Python**

```Python:Python3
print(ord('A'), ord('Z'), ord('a'), ord('z'))
# 65 90 97 122
print(chr(65), chr(90), chr(97), chr(122))
# A Z a z
```

**R**

```R:R
cat(charToRaw("A"), charToRaw("Z"), charToRaw("a"), charToRaw("z"))   #16進数
# 41 5a 61 7a
cat(strtoi(charToRaw("A"), 16L), strtoi(charToRaw("Z"), 16L), strtoi(charToRaw("a"), 16L), strtoi(charToRaw("z"), 16L))
# 65 90 97 122

cat(as.raw(65), as.raw(90), as.raw(97), as.raw(122))   #16進数
# 41 5a 61 7a
cat(rawToChar(as.raw(65)), rawToChar(as.raw(90)), rawToChar(as.raw(97)), rawToChar(as.raw(122)))
# A Z a z

charToRaw("AZaz")   #16進数
# 41 5a 61 7a
strtoi(charToRaw("AZaz"), 16L)
# 65  90  97 122

as.raw(c(65, 90, 97, 122))   #16進数
# 41 5a 61 7a
rawToChar(as.raw(c(65, 90, 97, 122)))
# "AZaz"
```

**VBA**

```VBA:VBA
Debug.Print Asc("A"), Asc("Z"), Asc("a"), Asc("z")
' 65            90            97            122
Debug.Print Chr(65), Chr(90), Chr(97), Chr(122)
' A             Z             a             z
```


# まとめ
### 一覧
各言語で使用する文字列操作関数等を一覧にまとめます。比較のために、EXCELでの計算も示しました。
s1 = "abc"
s2 = "def"
s3 = "ghij"
s = "abcdefghij"
t = "abcdefghijabcdefghij"
u = "abcDEFghij"
v = "ａｂｃＤＥＦｇｈｉｊ"
w = "  d   e    f     "
とします。また、EXCELのセルにそれぞれ
A1セル：="abc"
A2セル：="def"
A3セル：="ghij"
A4セル：="abcdefghij"
A5セル：="abcdefghijabcdefghij"
A6セル：="abcDEFghij"
A7セル：="ａｂｃＤＥＦｇｈｉｊ"
A8セル：="  d   e    f     "
が入力されているものとします。

#### 文字列の基本的操作
||Python|R|VBA|EXCEL|結果|
|:--|:--|:--|:--|:--|:--|:--|
|結合|s1 + s2 + s3|paste0(s1, s2, s3)<br>paste(s1, s2, s3, sep="")|s1 & s2 & s3|=A1&A2&A3<br>=CONCATENATE(<br>A1,A2,A3)|abcdefghij|
|長さ|len(s)|nchar(s)|Len(s)|=LEN(A4)|10|
|反転|s[::-1]||StrReverse(s)||jihgfedcba|
|繰り返し|'A' * 3||String(3, "A")|=REPT("A",3)|AAA|
|繰り返し|'def' * 3|||=REPT("def",3)|defdefdef|

#### 文字列の取り出し
||Python|R|VBA|EXCEL|結果|
|:--|:--|:--|:--|:--|:--|:--|
|左から|s[8:10]<br>s[0:2]<br>s[:2]|substr(s, 1, 2)<br>substring(s, 1, 2)|Left(s, 2)|=LEFT(A4,2)|ab|
|右から|s[len(s)-2:len(s)]<br>s[-2:]|substr(s, nchar(s)-2+1, nchar(s))|Right(s, 2)|=RIGHT(A4,2)|ij|
|途中|s[3:6]|substr(s, 4, 6)|Mid(s, 4, 3)|=MID(A4,4,3)|def|

#### 文字列の検索
||Python|R|VBA|EXCEL|結果|
|:--|:--|:--|:--|:--|:--|:--|
|検索|s.find('def')||InStr(1, s, "def")|=FIND("def",A4,1)<br>=SEARCH("def",A4,1)|3,4|
|後ろからの検索|t.rfind('def')|||InStrRev(t, "def")|13,14|
|カウント|t.count('def')||||2|

#### 文字列の置換
||Python|R|VBA|EXCEL|結果|
|:--|:--|:--|:--|:--|:--|:--|
|置換|s.replace('def', 'DEF')|sub("def", "DEF", s)|Replace(s, "def", "DEF")|=SUBSTITUTE(<br>A4,"def","DEF")<br>=REPLACE(A4,<br>FIND("def",A4),<br>LEN("def"),"DEF")|abcDEFghij|
|最初の1つだけ置換||sub("def", "DEF", t)|||abcDEFghijabcdefghij|
|すべて置換|t.replace('def', 'DEF')|gsub("def", "DEF", t)|Replace(t, "def", "DEF")|=SUBSTITUTE(<br>A5,"def","DEF")|abcDEFghijabcDEFghij|

#### 文字列の変換
||Python|R|VBA|EXCEL|結果|
|:--|:--|:--|:--|:--|:--|:--|
|大文字に|u.upper()|toupper(u)|UCase(u)|=UPPER(A6)|ABCDEFGHIJ|
|小文字に|u.lower()|tolower(u)|LCase(u)|=LOWER(A6)|abcdefghij|
|先頭のみ大文字・それ以外は小文字に|u.capitalize()||StrConv(u, vbProperCase)|=PROPER(A6)|Abcdefghij|
|大文字と小文字を入れ替え|u.swapcase()|chartr("A-Za-z", "a-zA-z", u)|||ABCdefGHIJ|
|大文字かどうかの判定|u.isupper()|u == toupper(u)|||False|
|小文字かどうかの判定|u.islower()|u == tolower(u)|||False|
|全角に||chartr("A-Za-z", "Ａ-Ｚａ-ｚ", u)|StrConv(u, vbWide)|=JIS(A6)|ａｂｃＤＥＦｇｈｉｊ|
|半角に||chartr("Ａ-Ｚａ-ｚ", "A-Za-z", v)|StrConv(v, vbNarrow)|=ASC(A7)|abcDEFghij|

#### 文字列のスペース
||Python|R|VBA|EXCEL|結果|
|:--|:--|:--|:--|:--|:--|:--|
|スペース|' ' * 3||Space(3)|=REPT(" ",3)|   |
|スペース削除|w.strip(' ')||Trim(w)|=TRIM(A8)|"d   e    f"|
||w.lstrip(' ')||LTrim(w)||"d   e    f     "|
||w.rstrip(' ')||RTrim(w)||"  d   e    f"|
EXCELのTRIM関数は文字列の中のスペースも1つを除いて削除されて`d e f`となります。

#### アスキーコード
||Python|R|VBA|EXCEL|結果|
|:--|:--|:--|:--|:--|:--|:--|
|AのASCIIコード|ord('A')|strtoi(charToRaw("A"), 16L)|Asc("A")|=CODE("A")|65|
|ZのASCIIコード|ord('Z')|strtoi(charToRaw("Z"), 16L)|Asc("Z")|=CODE("Z")|90|
|aのASCIIコード|ord('a')|strtoi(charToRaw("a"), 16L)|Asc("a")|=CODE("a")|97|
|zのASCIIコード|ord('z')|strtoi(charToRaw("z"), 16L)|Asc("z")|=CODE("a")|122|
|ASCIIコード65の文字|chr(65)|rawToChar(as.raw(65))|Chr(65)|=CHAR(65)|A|
|ASCIIコード90の文字|chr(90)|rawToChar(as.raw(90))|Chr(90)|=CHAR(90)|Z|
|ASCIIコード97の文字|chr(97)|rawToChar(as.raw(97))|Chr(97)|=CHAR(97)|a|
|ASCIIコード122の文字|chr(122)|rawToChar(as.raw(122))|Chr(122)|=CHAR(122)|z|


### プログラム全体
参考までに使ったプログラムの全体を示します。

**Python**

```Python:Python3
# 文字列の結合
s1 = 'abc'
s2 = 'def'
s3 = 'ghij'
print(s1 + s2 + s3)
# abcdefghij

# 文字列の長さ
s = 'abcdefghij'
print(len(s))
# 10

# 文字列の取り出し
s = 'abcdefghij'
print(s[0:2])
print(s[:2])
# ab
print(s[8:10])
print(s[len(s)-2:len(s)])
print(s[-2:])
# ij
print(s[3:6])
# def

# 文字列の検索
s = 'abcdefghij'
print(s.find('def'))
# 3
t = s + s # 'abcdefghijabcdefghij'
print(t.rfind('def'))
# 13
print(t.count('def'))
# 2
print('def' in t)
# True
print('def' not in t)
# False

# 文字列の置き換え
s = 'abcdefghij'
print(s.replace('def', 'DEF'))
# 'abcDEFghij'
t = s + s # 'abcdefghijabcdefghij'
print(t.replace('def', 'DEF'))
# 'abcDEFghijabcDEFghij'

# 文字列の大文字・小文字の変換
s = 'abcDEFghij'
print(s.upper())      # 大文字に
# ABCDEFGHIJ
print(s.lower())      # 小文字に
# abcdefghij
print(s.capitalize()) # 先頭のみ大文字・それ以外は小文字に
# Abcdefghij
print(s.swapcase())   # 大文字と小文字を入れ替え
# ABCdefGHIJ
print(s.isupper(), s.islower(), s.upper().isupper(), s.lower().islower())
# False False True True

# 文字列の全角・半角の変換
# 全角・半角の変換の組み込み関数はなさそう

# 文字列の反転
s = 'abcdefghij'
print(s[::-1])
# jihgFEDcba
t = ''
for i in range(len(s)):
    t = t + s[len(s)-i-1]
print(t)

# 文字列の繰り返し
print('A' * 3)
# AAA
print('def' * 3)
# defdefdef

# 文字列のスペース
s = ' ' * 3
print('-' + s + '-')
# -   -
s = ' '*2 + 'd' + ' '*3 + 'e' + ' '*4 + 'f' + ' '*5
print('-' + s + '-')
# -  d   e    f     -

# 文字列の前後のスペース削除
s = ' '*2 + 'd' + ' '*3 + 'e' + ' '*4 + 'f' + ' '*5
print(s.strip(' '))
# 'd   e    f'
print(s.lstrip(' '))
# 'd   e    f     '
print(s.rstrip(' '))
# '  d   e    f'

# アスキー(ASCII)コード
print(ord('A'), ord('Z'), ord('a'), ord('z'))
# 65 90 97 122
print(chr(65), chr(90), chr(97), chr(122))
# A Z a z
```

**R**

```R:R
# 文字列の結合
s1 <- "abc"
s2 <- "def"
s3 <- "ghij"
paste0(s1, s2, s3)
# "abcdefghij"
paste(s1, s2, s3)
# "abc def ghij"
paste(s1, s2, s3, sep="")
# "abcdefghij"
# paste関数はデフォルトでスペースが入る

# 文字列の長さ
s <- "abcdefghij"
nchar(s)
# 10
length(s)
# 1
# length関数は文字列の長さではなく、文字列ベクトルの要素数を返す

# 文字列の取り出し
s <- "abcdefghij"
substr(s, 1, 2)
# "ab"
substring(s, 1, 2)   # substrとほぼ同じ
# "ab"
substr(s, nchar(s)-2+1, nchar(s))
# "ij"
substr(s, 4, 6)
# "def"

# 文字列の検索
s <- "abcdefghij"
match("def", s) #完全一致
# NA
"def" %in% s    #完全一致
# FALSE
grep("def", s)  #部分一致（パターンマッチ）
# 1
# これはsという文字列ベクトルの1番目の要素(いまは要素は1つしかないが)に部分一致があったということ（1文字目ということではない）
regexpr("def", s)
# [1] 4
# attr(,"match.length")
# [1] 3
# attr(,"index.type")
# [1] "chars"
# attr(,"useBytes")
# [1] TRUE
regexpr("def", s)[1]
# [1] 4
t <- paste(s, s, sep="")
t
# [1] "abcdefghijabcdefghij"
gregexpr("def", t)
# [[1]]
# [1]  4 14
# attr(,"match.length")
# [1] 3 3
# attr(,"index.type")
# [1] "chars"
# attr(,"useBytes")
# [1] TRUE

# 文字列の置き換え
s <- "abcdefghij"
sub("def", "DEF", s)
# "abcDEFghij"
t <- paste(s, s, sep="") # "abcdefghijabcdefghij"
sub("def", "DEF", t)  # 最初の1つだけ置換
# "abcDEFghijabcdefghij"
gsub("def", "DEF", t) # すべて置換
# "abcDEFghijabcDEFghij"

# 文字列の大文字・小文字の変換
s <- "abcDEFghij"
toupper(s)              # 大文字に
chartr("a-z", "A-Z", s) # 大文字に
# "ABCDEFGHIJ"
tolower(s)              # 小文字に
chartr("A-Z", "a-z", s) # 小文字に
# "abcdefghij"
paste0(substr(toupper(s),1,1), substr(tolower(s),2,nchar(s))) # 先頭のみ大文字・それ以外は小文字に
# "Abcdefghij"
chartr("A-Za-z", "a-zA-z", s)  #大文字・小文字を入れ替え
# "ABCdefGHIJ"
s == toupper(s)  #すべて大文字かどうかの判定
# FALSE
s == tolower(s)  #すべて小文字かどうかの判定
# FALSE

# 文字列の全角・半角の変換
s <- "abcDEFghij"
chartr("A-Za-z", "Ａ-Ｚａ-ｚ", s)  # 半角を全角に
# "ａｂｃＤＥＦｇｈｉｊ"
chartr("Ａ-Ｚａ-ｚ", "A-Za-z", chartr("A-Za-z", "Ａ-Ｚａ-ｚ", s))  # 全角を半角に
# "abcDEFghij"

# 文字列の反転
s <- "abcdefghij"
t <- ""
for (i in 1:nchar(s)) {
  t <- paste0(t, substr(s, nchar(s)-i+1, nchar(s)-i+1))
}
t
# "jihgfedcba"

# 文字列の繰り返し
rep("A", 3)
# "A" "A" "A"
paste(rep("A", 3), collapse="")
# "AAA"
paste(rep("def", 3), collapse="")
# "defdefdef"

# 文字列のスペース
s <- paste(rep(" ", 3), collapse="")
paste("-", s, "-", sep="")
# "-   -"
s <- paste("-",
           paste(rep(" ", 2), collapse=""), 
           "d", 
           paste(rep(" ", 3), collapse=""),
           "e",
           paste(rep(" ", 4), collapse=""),
           "f",
           paste(rep(" ", 5), collapse=""),
           "-",
           sep="")
s
# "-  d   e    f     -"

# 文字列の前後のスペース削除
# トリム関数はなさそう

# アスキー(ASCII)コード
cat(charToRaw("A"), charToRaw("Z"), charToRaw("a"), charToRaw("z"))   #16進数
# 41 5a 61 7a
cat(strtoi(charToRaw("A"), 16L), strtoi(charToRaw("Z"), 16L), strtoi(charToRaw("a"), 16L), strtoi(charToRaw("z"), 16L))
# 65 90 97 122

cat(as.raw(65), as.raw(90), as.raw(97), as.raw(122))   #16進数
# 41 5a 61 7a
cat(rawToChar(as.raw(65)), rawToChar(as.raw(90)), rawToChar(as.raw(97)), rawToChar(as.raw(122)))
# A Z a z

charToRaw("AZaz")   #16進数
# 41 5a 61 7a
strtoi(charToRaw("AZaz"), 16L)
# 65  90  97 122

as.raw(c(65, 90, 97, 122))   #16進数
# 41 5a 61 7a
rawToChar(as.raw(c(65, 90, 97, 122)))
# "AZaz"
```

**VBA**

```VBA:VBA
Sub test_string()

Dim s1 As String
Dim s2 As String
Dim s3 As String
Dim s As String
Dim t As String

' 文字列の結合
s1 = "abc"
s2 = "def"
s3 = "ghij"
Debug.Print s1 & s2 & s3
' abcdefghij

' 文字列の長さ
s = "abcdefghij"
Debug.Print Len(s)
' 10

' 文字列の取り出し
s = "abcdefghij"
Debug.Print Left(s, 2)
' ab
Debug.Print Right(s, 2)
' ij
Debug.Print Mid(s, 4, 3)
' def

' 文字列の検索
s = "abcdefghij"
Debug.Print InStr(1, s, "def")
' 4
Debug.Print InStr(1, s, "DEF")
' 0
t = s & s ' abcdefghijabcdefghij
Debug.Print InStrRev(t, "def") '後ろから検索
' 14

' 文字列の置き換え
s = "abcdefghij"
Debug.Print Replace(s, "def", "DEF")
' abcDEFghij
t = s & s ' abcdefghijabcdefghij
Debug.Print Replace(t, "def", "DEF")
' abcDEFghijabcDEFghij

' 文字列の大文字・小文字の変換
s = "abcDEFghij"
Debug.Print UCase(s)                 ' 大文字に
Debug.Print StrConv(s, vbUpperCase)  ' 大文字に
' ABCDEFGHIJ
Debug.Print LCase(s)                 ' 小文字に
Debug.Print StrConv(s, vbLowerCase)  ' 小文字に
' abcdefghij
Debug.Print UCase(Left(s, 1)) & Right(LCase(s), Len(s) - 1) ' 先頭のみ大文字・それ以外は小文字に
Debug.Print StrConv(s, vbProperCase) ' 先頭のみ大文字・それ以外は小文字に
' Abcdefghij

' 文字列の全角・半角の変換
' Abcdefghij
s = "abcDEFghij"
Debug.Print StrConv(s, vbWide)                    ' 全角へ
' ａｂｃＤＥＦｇｈｉｊ
Debug.Print StrConv(StrConv(s, vbWide), vbNarrow) ' 半角へ
' abcDEFghij

' 文字列の反転
s = "abcdefghij"
Debug.Print StrReverse(s)
' jihgfedcba

' 文字列の繰り返し
Debug.Print String(3, "A")
' AAA
Debug.Print String(3, "def")
' ddd
Dim i As Integer
s = ""
For i = 1 To 3
    s = s & "def"
Next i
Debug.Print s
' defdefdef

' 文字列のスペース
s = Space(3)
Debug.Print "-" & s & "-"
' -   -
s = Space(2) & "d" & Space(3) & "e" & Space(4) & "f" & Space(5)
Debug.Print "-" & s & "-"
' -  d   e    f     -

' 文字列の前後のスペース削除
s = Space(2) & "d" & Space(3) & "e" & Space(4) & "f" & Space(5)
Debug.Print "-" & Trim(s) & "-"
' -d   e    f-
Debug.Print "-" & LTrim(s) & "-"
' -d   e    f     -
Debug.Print "-" & RTrim(s) & "-"
' -  d   e    f-

' アスキー(ASCII)コード
Debug.Print Asc("A"), Asc("Z"), Asc("a"), Asc("z")
' 65            90            97            122
Debug.Print Chr(65), Chr(90), Chr(97), Chr(122)
' A             Z             a             z

End Sub
```


# 参考
- Python
   - [Python チュートリアル](https://docs.python.org/ja/3/tutorial/index.html)
      - [3.1.2. 文字列型 (string)](https://docs.python.org/ja/3/tutorial/introduction.html#strings) 
   - [Chainer チュートリアル　2. Python 入門](https://tutorials.chainer.org/ja/02_Basics_of_Python.html)
- R
   - [RjpWiki](http://www.okadajp.org/RWiki/)
      - [Rの文字列処理関数](http://www.okadajp.org/RWiki/?R%E3%81%AE%E6%96%87%E5%AD%97%E5%88%97%E5%87%A6%E7%90%86%E9%96%A2%E6%95%B0)
   - [R-Tips](http://cse.naro.affrc.go.jp/takezawa/r-tips/r.html)