はじめに:Next.jsでサイト制作を学んでいて困ったこと
最近、Next.jsでのサイト制作を学び始めています。
既存のHTMLサイト(静的なWebページ)をNext.jsで作り直す学びなのですが、その課題の中に、index.html
の中のフッター部分をNext.js用のReactコンポーネント化して、Footer.tsx
というファイルに分けようとしていたときのことです。
元の
index.html
のフッター部分はこんな感じでした(コードはシンプルにしています。):
<!-- index.html の一部 -->
<footer class="p-footer">
<h2 class="p-footer__title">会社情報</h2>
<ul class="p-footer__list">
<li class="p-footer__item">
<a href="#" class="p-footer__link">会社概要</a>
</li>
<li class="p-footer__item">
<a href="#" class="p-footer__link">お問い合わせ</a>
</li>
</ul>
<p class="p-footer__copyright">© 2024 Company Name</p>
</footer>
これを
Footer.tsx
というNext.js用のReactコンポーネントに変換して、CSS
Modulesを使う形にすると言う作業です。つまり、こうしたい:
// Footer.tsx
import styles from './Footer.module.css'
export default function Footer() {
return (
<footer className={styles.pFooter}>
<h2 className={styles.title}>会社情報</h2>
<ul className={styles.list}>
<li className={styles.item}>
<a href="#" className={styles.link}>会社概要</a>
</li>
<li className={styles.item}>
<a href="#" className={styles.link}>お問い合わせ</a>
</li>
</ul>
<p className={styles.copyright}>© 2024 Company Name</p>
</footer>
)
}
具体的に変更が必要なのは:
class→classNameに変更-
"p-footer__title"→{styles.title}のように変換 - BEM記法の
p-footer__という接頭辞を削除
手作業で一つずつ変えるのはとても大変で、コピペミスやタイポ(typographical error)も起きてしまいそうです。これを、便利に一斉置換する方法があるのですが、それが、「正規表現」を使って、「後方参照」して置換する方法なんです。そこで出てきた「正規表現」と「後方参照」という言葉が難しかったので調べてみました。
一斉置換する方法
言葉の意味の説明の前に、今回学んだ一斉置換する方法は、こんな感じです。
VSCodeでの操作(Mac):
- ⌥ + ⌘ + F で置換画面を開く
-
検索欄の右側にある
.*の「正規表現を使用する」アイコンをクリック - 検索欄に:
class="p-footer__(.+)" - 置換欄に:
className={styles.$1} - すべて置換ボタンをクリック(⌘ + Enter)
そしたら...
<!-- 一瞬で変換される! -->
class="p-footer__title" → className={styles.title}
class="p-footer__list" → className={styles.list}
class="p-footer__item" → className={styles.item}
class="p-footer__link" → className={styles.link}
class="p-footer__copyright" → className={styles.copyright}
めちゃくちゃ便利です! 本当に一発で全部変換できて、感動しました。
そもそも「正規表現」とは?
今回の学びの中で「正規表現を使って一斉置換する」って出てきたんですが、「正規表現」という言葉自体がわかりませんでした。
英語で調べてみると、Regular Expression という言葉でした。
- Regular = 規則的な、パターンのある
- Expression = 表現
ですので、「規則的なパターンで文字列を表現する方法」という意味だそうです。
日本語の「正規」って言葉が堅苦しくて、何か特別で難しい技術のように感じてしまいそうですが、英語で見ると「パターンで文字列を表す書き方」くらいのシンプルな意味でした。ちなみに「正規」という訳は数学用語の翻訳の歴史の名残りだそうです。
普通の検索との違い
普通の検索(⌘ + F)だと、例えば
class="p-footer__title"
と入力したら、その文字列と完全に一致するものしか見つかりません。
でも正規表現を使用すると、パターンで検索できるんです。
私の場合だと:
-
普通の検索:
class="p-footer__title"だけが見つかる -
正規表現:
class="p-footer__○○"というパターン全部が見つかる
○○ の部分が何であっても、p-footer__
の後に何か文字があれば全部マッチする。これが正規表現の便利なところでした。
だからこそ、複数のクラス名を一度に変換できるわけなんです。
(.+) とは?
次に、検索欄に入れた class="p-footer__(.+)" の中の
(.+) とは何でしょうか?
正規表現にはいろいろな記号があって、それぞれ特別な意味があるそうです。
記号の意味:
.= 任意の1文字(何でもOK)+= 1回以上繰り返す()= 記憶する(超重要!)
.+ は「何か文字が1文字以上」
この2つを組み合わせた
.+ は「何でもいいから1文字以上」という意味です。
「title」でも「link」でも「copyright」でも、とにかく何か文字があればマッチします。
パターン全体の意味
class="p-footer__(.+)" を分解すると:
class="p-footer__ → 固定(決まった文字列)
(.+) → 変動(何でもいい1文字以上)← ココが変わる部分!
" → 固定(ダブルクォートで終わる)
実際にマッチする例
class="p-footer__title" → title の部分が (.+) にマッチ
class="p-footer__link" → link の部分が (.+) にマッチ
class="p-footer__copyright" → copyright の部分が (.+) にマッチ
ポイント:括弧 () で囲んだ部分は記憶される!
これが次に出てくる「後方参照」につながる重要なポイントです。
$1 と「後方参照」の意味
なお、置換欄に書いた className={styles.$1} の
$1の部分
が、これが「後方参照」と呼ばれる機能なんですが、この「後方参照」という言葉も英語で調べてみると、Backreference
という言葉でした。
Backreference を分解してみる
- Back = 後ろ、戻る、振り返る
- Reference = 参照する、見る
Backreference = 後ろを振り返って参照する
最初は「やっぱり後ろって何が後ろなの?」と思ったんですが、よく調べてみると、英語の「back」には時間的に戻る、過去を振り返るという意味があることがわかりました。
例えば:
- look back = 振り返る(過去を思い出す)
- go back = 戻る(以前の場所や時間に)
- way back = ずっと前
つまり、Backreference = 以前の内容を参照するという意味だったんです!
日本語の「後方」という言葉の難しさ
「後方参照」という言葉が直観的に分かりにくい理由を整理してみました。
日本語の「後ろ」「後方」にも時間的な過去を表す使い方があります:
- 「後ろを振り返る」= 過去を思い出す
- 「後の祭り」= 終わった後、手遅れ
だから「後方参照 = 以前の内容を参照する」という意味なんです。
でも、そうだと日本語ではすぐに分かりにくい理由
それは「後」という言葉が3つの意味を持つからでした:
| 意味 | 例 |
|---|---|
| 時間的に未来 | 後で連絡する、後日お知らせします |
| 時間的に過去 | 後ろを振り返る、後の祭り |
| 空間的に背後 | 後方確認、後方から接近 |
同じ「後」でも、日本語では、時間的には未来も過去も両方表せるんです。
さらに、日常で「後方」と言えば、圧倒的に「背後」の意味で使います:
- 車の「後方確認」
- 「後方注意」
- 「後方からの攻撃」
だから混乱する
「後方参照」と聞いたとき、こんなふうに迷ってしまいます:
❓ 「後」には未来の意味もある
→ これから参照する?
❓ 「後方」は普通、背後のこと
→ 背後にあるものを参照する?
❓ 専門用語っぽくて堅苦しい
→ そもそも意味がつかみにくい...
混乱の原因まとめ:
- 「後」が未来も過去も表せる多義性
- 「後方」の空間的イメージ(背後)が強すぎる
- 専門用語として取っつきにくい
わかりやすい言い換え:
後方参照→ 以前の内容を参照 ⭕-
後方参照→ 記憶した内容を呼び出す ⭕
実際はこういうこと
言葉の意味がわかると、動作もイメージしやすくなりました。
正規表現を使うと、複数のパターンを一度に処理できます:
検索時(記憶):
class="p-footer__(.+)"
^^^^
この部分を記憶(何が入っても記憶する)
マッチ例:
class="p-footer__title" → "title" を記憶
class="p-footer__link" → "link" を記憶
class="p-footer__copyright" → "copyright" を記憶
置換時(呼び出し):
className={styles.$1}
^^
それぞれ記憶した内容を使う
結果:
className={styles.title}
className={styles.link}
className={styles.copyright}
過去(検索)で記憶した内容を、現在(置換)で参照する。時間を遡って情報を取り出すから「Backreference = 後方参照」なんですね。
プログラミング用語は英語で理解すると楽
今回の経験で改めて思ったのは、プログラミング用語は英語の意味から理解した方が腑に落ちるということです。
「後方参照」のように、日本語訳は間違っていないのに、多義性や日常的なイメージとのズレで混乱することがあります。
他の用語も英語で見ると納得できます:
- コンポーネント(component)= 部品
- プロップス(props)= properties の略
- ステート(state)= 状態
英語で見ると「なるほど!」ってなることが多いんです。
まとめ
Regular Expression(正規表現)
→ パターンで文字列を表現する技術
Backreference(後方参照)
→ 以前記憶した内容を参照する技術
→ 「後」の多義性と空間的イメージで混乱しやすい
言葉の意味がわかれば、正規表現も後方参照も、実はシンプルな機能でした。
VSCodeで ⌥ + ⌘ + F を押して、正規表現モード(.*
正規表現を使うアイコン)をONにすれば、使えます。
同じように専門用語で躓いている人の参考になれば嬉しいです!