第11章 文字列操作
11.1 文字列リテラル
PHP
<?php
// シングルクォート(変数展開なし)
$single = 'Hello, World!';
$escaped = 'It\'s a test';
// ダブルクォート(変数展開あり)
$name = "John";
$double = "Hello, $name!";
$complex = "Hello, {$name}!";
// ヒアドキュメント(変数展開あり)
$heredoc = <<<EOT
This is a
multi-line string.
Hello, $name!
EOT;
// Nowdoc(変数展開なし)
$nowdoc = <<<'EOT'
This is a
multi-line string.
No variable expansion: $name
EOT;
TypeScript
// シングルクォート
const single = 'Hello, World!';
// ダブルクォート
const double = "Hello, World!";
// テンプレートリテラル(バッククォート)
const name = "John";
const template = `Hello, ${name}!`;
// 複数行
const multiline = `
This is a
multi-line string.
Hello, ${name}!
`;
// タグ付きテンプレート
function highlight(strings: TemplateStringsArray, ...values: unknown[]) {
return strings.reduce((result, str, i) =>
result + str + (values[i] ? `<mark>${values[i]}</mark>` : ''), '');
}
const highlighted = highlight`Hello, ${name}!`; // "Hello, <mark>John</mark>!"
VB.NET
' ダブルクォートのみ
Dim s As String = "Hello, World!"
' エスケープ(二重ダブルクォート)
Dim escaped As String = "He said ""Hello"""
' 文字列補間(VB 14+)
Dim name As String = "John"
Dim interpolated As String = $"Hello, {name}!"
' 書式指定
Dim price As Decimal = 1234.5D
Dim formatted As String = $"Price: {price:C}" ' Price: ¥1,235
' 複数行(& と vbCrLf)
Dim multiline As String = "Line 1" & vbCrLf &
"Line 2" & vbCrLf &
"Line 3"
' 逐語的文字列リテラルはない(C# の @"..." に相当するものはない)
11.2 文字列補間/テンプレートリテラル
PHP
<?php
$name = "John";
$age = 30;
// 基本的な変数展開
$message = "Name: $name, Age: $age";
// 複雑な式は波括弧
$message = "Next year: {$age + 1}"; // エラー:式は不可
$nextAge = $age + 1;
$message = "Next year: $nextAge"; // 変数を使う
// 配列アクセス
$user = ['name' => 'John'];
$message = "Name: {$user['name']}";
// メソッド呼び出し
class User {
public function getName(): string { return "John"; }
}
$user = new User();
$message = "Name: {$user->getName()}";
TypeScript
const name = "John";
const age = 30;
// 基本
const message = `Name: ${name}, Age: ${age}`;
// 式
const nextYear = `Next year: ${age + 1}`;
// 三項演算子
const status = `Status: ${age >= 18 ? 'Adult' : 'Minor'}`;
// 関数呼び出し
const upper = `Upper: ${name.toUpperCase()}`;
// ネスト
const nested = `Result: ${`Hello, ${name}`}`;
// 複数行と式
const html = `
<div>
<h1>${name}</h1>
<p>Age: ${age}</p>
</div>
`;
VB.NET
Dim name As String = "John"
Dim age As Integer = 30
' 基本
Dim message As String = $"Name: {name}, Age: {age}"
' 式
Dim nextYear As String = $"Next year: {age + 1}"
' 三項演算子(If演算子)
Dim status As String = $"Status: {If(age >= 18, "Adult", "Minor")}"
' メソッド呼び出し
Dim upper As String = $"Upper: {name.ToUpper()}"
' 書式指定
Dim price As Decimal = 1234.567D
Dim formatted As String = $"Price: {price:N2}" ' Price: 1,234.57
Dim percent As Double = 0.1234
Dim pct As String = $"Rate: {percent:P1}" ' Rate: 12.3%
Dim today As Date = Date.Now
Dim dateStr As String = $"Date: {today:yyyy-MM-dd}"
' 配置(幅指定)
Dim left As String = $"|{name,-10}|" ' |John |
Dim right As String = $"|{name,10}|" ' | John|
' 複合
Dim complex As String = $"|{price,15:C2}|" ' | ¥1,234.57|
11.3 エスケープシーケンス
| シーケンス | PHP | TypeScript | VB.NET |
|---|---|---|---|
| 改行 | \n |
\n |
vbLf または Chr(10)
|
| 復帰 | \r |
\r |
vbCr または Chr(13)
|
| 改行+復帰 | \r\n |
\r\n |
vbCrLf |
| タブ | \t |
\t |
vbTab |
| バックスラッシュ | \\ |
\\ |
N/A |
| クォート |
\" または \'
|
\" または \'
|
"" |
| NULL | \0 |
\0 |
vbNullChar |
| Unicode | \u{1F600} |
\u{1F600} |
ChrW(&H1F600) |
PHP
<?php
// ダブルクォート内でのみ有効
$escaped = "Line1\nLine2\tTabbed";
// Unicode
$emoji = "\u{1F600}"; // PHP 7+
// シングルクォート内ではリテラル
$literal = 'This is \n not a newline';
TypeScript
// 通常の文字列
const escaped = "Line1\nLine2\tTabbed";
// テンプレートリテラル
const template = `Line1
Line2`; // 実際の改行も可
// Unicode
const emoji = "\u{1F600}";
const emoji2 = "\uD83D\uDE00"; // サロゲートペア
VB.NET
' VB.NET にはエスケープシーケンスがない
' 定数を使用
Dim escaped As String = "Line1" & vbCrLf & "Line2" & vbTab & "Tabbed"
' または Chr/ChrW 関数
Dim newline As String = "Line1" & Chr(13) & Chr(10) & "Line2"
' Unicode
Dim emoji As String = ChrW(&H1F600)
' 定数一覧
' vbCrLf - キャリッジリターン + ラインフィード
' vbCr - キャリッジリターン
' vbLf - ラインフィード
' vbTab - タブ
' vbBack - バックスペース
' vbNewLine - プラットフォーム固有の改行
' vbNullChar - Null文字
' vbNullString - Null文字列(Nothing とは異なる)
11.4 文字列操作メソッド
長さと文字アクセス
<?php
$str = "Hello, World!";
// 長さ
echo strlen($str); // 13(バイト数)
echo mb_strlen($str); // マルチバイト対応
// 文字アクセス
echo $str[0]; // H
echo $str[-1]; // !(PHP 7.1+)
echo mb_substr($str, 0, 1); // マルチバイト対応
const str = "Hello, World!";
// 長さ
console.log(str.length); // 13
// 文字アクセス
console.log(str[0]); // H
console.log(str.charAt(0)); // H
console.log(str.at(-1)); // !(ES2022)
// コードポイント
console.log(str.charCodeAt(0)); // 72
console.log(str.codePointAt(0)); // 72
Dim str As String = "Hello, World!"
' 長さ
Console.WriteLine(str.Length) ' 13
' 文字アクセス
Console.WriteLine(str(0)) ' H
Console.WriteLine(str.Chars(0)) ' H
' Unicodeコードポイント
Console.WriteLine(AscW(str(0))) ' 72
検索
<?php
$str = "Hello, World!";
strpos($str, "World"); // 7(位置)
strpos($str, "xyz"); // false(見つからない)
stripos($str, "world"); // 7(大文字小文字無視)
strrpos($str, "o"); // 8(最後の出現位置)
str_contains($str, "World"); // true(PHP 8.0+)
str_starts_with($str, "Hello"); // true(PHP 8.0+)
str_ends_with($str, "!"); // true(PHP 8.0+)
const str = "Hello, World!";
str.indexOf("World"); // 7
str.indexOf("xyz"); // -1
str.lastIndexOf("o"); // 8
str.includes("World"); // true
str.startsWith("Hello"); // true
str.endsWith("!"); // true
// 正規表現検索
str.search(/World/); // 7
str.match(/o/g); // ["o", "o"]
Dim str As String = "Hello, World!"
str.IndexOf("World") ' 7
str.IndexOf("xyz") ' -1
str.LastIndexOf("o") ' 8
str.Contains("World") ' True
str.StartsWith("Hello") ' True
str.EndsWith("!") ' True
' 大文字小文字無視
str.IndexOf("world", StringComparison.OrdinalIgnoreCase) ' 7
変換
<?php
$str = "Hello, World!";
strtoupper($str); // HELLO, WORLD!
strtolower($str); // hello, world!
ucfirst($str); // Hello, World!
ucwords("hello world"); // Hello World
trim(" hello "); // "hello"
ltrim(" hello "); // "hello "
rtrim(" hello "); // " hello"
str_replace("World", "PHP", $str); // Hello, PHP!
str_ireplace("world", "PHP", $str); // 大文字小文字無視
substr($str, 0, 5); // Hello
substr($str, -6); // World!
str_pad("123", 5, "0", STR_PAD_LEFT); // "00123"
const str = "Hello, World!";
str.toUpperCase(); // HELLO, WORLD!
str.toLowerCase(); // hello, world!
" hello ".trim(); // "hello"
" hello ".trimStart(); // "hello "
" hello ".trimEnd(); // " hello"
str.replace("World", "TS"); // Hello, TS!
str.replaceAll("o", "0"); // Hell0, W0rld!
str.replace(/World/gi, "TS"); // 正規表現
str.substring(0, 5); // Hello
str.slice(-6); // World!
"123".padStart(5, "0"); // "00123"
"123".padEnd(5, "0"); // "12300"
str.repeat(2); // Hello, World!Hello, World!
Dim str As String = "Hello, World!"
str.ToUpper() ' HELLO, WORLD!
str.ToLower() ' hello, world!
" hello ".Trim() ' "hello"
" hello ".TrimStart() ' "hello "
" hello ".TrimEnd() ' " hello"
str.Replace("World", "VB") ' Hello, VB!
str.Substring(0, 5) ' Hello
str.Substring(7) ' World!
"123".PadLeft(5, "0"c) ' "00123"
"123".PadRight(5, "0"c) ' "12300"
String.Concat(str, str) ' 連結
String.Join(", ", {"a", "b", "c"}) ' "a, b, c"
' StringBuilder(効率的な文字列構築)
Dim sb As New StringBuilder()
sb.Append("Hello")
sb.AppendLine(", World!")
sb.Insert(0, "Say: ")
Dim result = sb.ToString()
分割と結合
<?php
// 分割
$parts = explode(",", "a,b,c"); // ["a", "b", "c"]
$parts = preg_split("/,\s*/", "a, b, c"); // 正規表現
// 結合
$joined = implode(", ", ["a", "b", "c"]); // "a, b, c"
// 文字配列に分割
$chars = str_split("Hello"); // ["H", "e", "l", "l", "o"]
$chars = mb_str_split("こんにちは"); // マルチバイト対応
// 分割
const parts = "a,b,c".split(","); // ["a", "b", "c"]
const chars = "Hello".split(""); // ["H", "e", "l", "l", "o"]
const limited = "a,b,c,d".split(",", 2); // ["a", "b"]
// 結合
const joined = ["a", "b", "c"].join(", "); // "a, b, c"
// スプレッド構文で文字配列
const charArray = [..."Hello"]; // ["H", "e", "l", "l", "o"]
' 分割
Dim parts = "a,b,c".Split(","c) ' {"a", "b", "c"}
Dim parts2 = "a, b, c".Split({", "}, StringSplitOptions.None)
' 結合
Dim joined = String.Join(", ", {"a", "b", "c"}) ' "a, b, c"
' 文字配列
Dim chars = "Hello".ToCharArray() ' {"H"c, "e"c, "l"c, "l"c, "o"c}
11.5 マルチバイト文字の扱い
PHP
<?php
$str = "こんにちは";
// バイト数 vs 文字数
echo strlen($str); // 15(UTF-8で3バイト×5文字)
echo mb_strlen($str); // 5
// 部分文字列
echo mb_substr($str, 0, 2); // こん
// エンコーディング変換
$sjis = mb_convert_encoding($str, "SJIS", "UTF-8");
$utf8 = mb_convert_encoding($sjis, "UTF-8", "SJIS");
// 正規表現(マルチバイト対応)
preg_match('/\p{Han}/u', '漢字'); // Unicode プロパティ
// 文字幅(東アジア)
echo mb_strwidth("Hello"); // 5
echo mb_strwidth("こんにちは"); // 10(全角は2)
TypeScript
const str = "こんにちは";
// JavaScript/TypeScript は UTF-16
console.log(str.length); // 5
// 絵文字など(サロゲートペア)
const emoji = "👨👩👧👦";
console.log(emoji.length); // 11(サロゲートペアと ZWJ)
// 正しい文字数
console.log([...emoji].length); // 7(コードポイント単位)
// Intl.Segmenter(書記素単位)
const segmenter = new Intl.Segmenter('ja', { granularity: 'grapheme' });
const segments = [...segmenter.segment(emoji)];
console.log(segments.length); // 1
// コードポイントでのイテレーション
for (const char of str) {
console.log(char);
}
// TextEncoder/TextDecoder
const encoder = new TextEncoder();
const bytes = encoder.encode(str); // Uint8Array
const decoder = new TextDecoder('utf-8');
const decoded = decoder.decode(bytes);
VB.NET
Dim str As String = "こんにちは"
' .NET は UTF-16
Console.WriteLine(str.Length) ' 5
' 絵文字
Dim emoji As String = "👨👩👧👦"
Console.WriteLine(emoji.Length) ' 11(サロゲートペアと ZWJ)
' StringInfo で書記素単位
Dim si As New StringInfo(emoji)
Console.WriteLine(si.LengthInTextElements) ' 1
' 書記素単位でのイテレーション
Dim enumerator = StringInfo.GetTextElementEnumerator(str)
While enumerator.MoveNext()
Console.WriteLine(enumerator.Current)
End While
' エンコーディング変換
Dim utf8Bytes = Encoding.UTF8.GetBytes(str)
Dim sjisBytes = Encoding.GetEncoding("Shift_JIS").GetBytes(str)
Dim decoded = Encoding.UTF8.GetString(utf8Bytes)
' バイト数
Console.WriteLine(Encoding.UTF8.GetByteCount(str)) ' 15