質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

5560閲覧

Pythonの正規表現について

keip

総合スコア33

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2019/02/13 07:37

pythonの正規表現についての質問です。

ある学習の中で、「~ / ~」「~ / ~」というような文字列をreモジュールのsplitにて分けるというものがありました。
この際、その学習の中では次のように解説していました。

b = re.split('\s*[//\t]+\s*', a)

※aとbはそれぞれ変数名です。

ここで疑問なのは、なぜ"\s*[///t]+\s*"とせず、\sとし、\sを打ち消しているのでしょうか?
ちなみに、この場合\sでも\sでも同じように動作するため違いがわかりませんでした。
また\sの時、\sは\によって打ち消されるため、\sは文字列として認識されると思ったのですが、そうではないのでしょうか。

回答してくださる方おりましたらよろしくお願い致します。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

この場合\sでも\sでも同じように動作するため

\sで動作しますか? 試してみたところ、動作しますね。

Python

1import re 2re.compile('\s')

実行結果 Wandbox

prog.py:2: SyntaxWarning: invalid escape sequence \s re.compile('\s')

追記: 警告を例外に見間違えました。とんだ凡ミスです。失礼しました。


ここで疑問なのは、なぜ"\s*[///t]+\s*"とせず、\sとし、\sを打ち消しているのでしょうか?

リファレンスに解説があります。

正規表現では、特殊な形式を表したり、特殊文字の持つ特別な意味を呼び出さずにその特殊な文字を使えるようにするために、バックスラッシュ文字 ('') を使います。こうしたバックスラッシュの使い方は、 Python の文字列リテラルにおける同じバックスラッシュ文字と衝突を起こします。例えば、バックスラッシュ自体にマッチさせるには、パターン文字列として '\' と書かなければなりません、というのも、正規表現は \ でなければならず、さらに正規な Python 文字列リテラルでは各々のバックスラッシュを \ と表現せねばならないからです。

正規表現パターンに Python の raw string 記法を使えばこの問題を解決できます。 'r' を前置した文字列リテラル内ではバックスラッシュを特別扱いしません。従って、 "\n" が改行一文字の入った文字列になるのに対して、 r"\n" は '' と 'n' という二つの文字の入った文字列になります。通常、 Python コード中では、パターンをこの raw string 記法を使って表現します。

引用元:Python 標準ライブラリ » re — 正規表現操作

『\で\sを打ち消している』のではなく、『\sで\sを表現している』ですかね。

assert '\s' == '\s' の謎

標準の C とは違い、認識されなかったエスケープシーケンスはすべて、そのまま文字列中に残ります。すなわち、バックスラッシュも結果中に残ります。(この挙動はデバッグの際に便利です: エスケープシーケンスが誤入力されたら、その出力結果が失敗しているのが分かりやすくなります。) 文字列中でのみ認識されるエスケープシーケンスは、バイト列リテラルには、認識されないエスケープシーケンスとして分類されるので注意してください。

バージョン 3.6 で変更: 認識されないエスケープシーケンスには DeprecationWarning が出ます。将来どこかのバージョンの Python で、認識されないエスケープシーケンスは SyntaxError になるでしょう。

引用元:Python 言語リファレンス » 字句解析

便利かこれ...?

Python

1assert '\s' == '\s' 2print('s is ok') 3 4assert '\t' == '\t' 5print('t is ok')

実行結果 CPython 3.6.2 @ Wandbox

s is ok Traceback (most recent call last): File "prog.py", line 4, in <module> assert '\t' == '\t' AssertionError

投稿2019/02/13 07:45

編集2019/02/13 08:06
LouiS0616

総合スコア35660

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hayataka2049

2019/02/13 07:51

質問文のままだと実行はできますね。結果の同一性は実のところよくわかりませんが・・・(この辺の仕様にそこまで詳しくない)
keip

2019/02/13 07:52

LouiS0616さん 回答ありがとうございます。 私がやった時には\sでも、\sと同じ働きをしました。 解説の引用を教えてくださりありがとうございます。読んでみます。
LouiS0616

2019/02/13 07:56

@hayataka2049 さん assert '\s' == '\s' が通りますね... 警告が出るだけで、良しなにエスケープしてくれる仕様なのかもしれません。
keip

2019/02/13 08:13

LouiS0616さん hayataka2049さんの回答で、私個人的な疑問は解消できました。LouiS0616さんもご回答くださりありがとうございました。 今後学習が進む中で必要になってくる内容かとも思いますので、参考にさせていただきます。
guest

0

ベストアンサー

python文字列そのもののエスケープシーケンスがあるため、\を表現するためには\と書かないと危ないからです。

たとえば

python

1>>> print("\t") # \tと表示 2\t 3>>> print("\t") # tab文字が出てくる。 4

まあ、\sというエスケープシーケンスはないので、その場合はどちらでも同じになるのかな? というような気もしますが・・・ちょっと詳細は不明。

なお、文字列の先頭にrをつけてr"文字列"のようにすると、エスケープシーケンスが効かなくなり書いた通りの文字列になるので、余計な手間が省けます。読みやすいので、正規表現をするときはだいたいこれを使うと思います。

python

1>>> print(r"\t") 2\t 3>>> print(r"\t") 4\t

投稿2019/02/13 07:49

編集2019/02/13 07:52
hayataka2049

総合スコア30933

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

keip

2019/02/13 07:57

hayataka2049さん 回答ありがとうございます。 なるほど。少し理解できました。 そこで疑問なのですが、\sと記載した場合には文字列のままの意味の「\s」とは処理されないのでしょうか? そうであれば「\s」という文字列との一致を探す場合には。どのように書きますか? 言ってることがわからなかったらすみません。
hayataka2049

2019/02/13 08:15 編集

"\s"あるいはr"\s"だと任意の空白文字とマッチします(一般的な正規表現)。 \sそのものとマッチさせたい場合は"\\s"あるいはr"\s"とします。"\\s"というのはpythonのエスケープをかいくぐるために2回、正規表現のエスケープをかいくぐるために2回書いている訳です。 \が4つも繋がるのはさすがにきもいので、rを付けたほう(raw stringsとか呼んだりします)がおすすめです。
keip

2019/02/13 08:11

ご回答ありがとうございます。 そうなんですね。 \sでは、1つ目の\によって\sをそのままの文字列として認識させると思っていたため、\sとすれば、\sという文字列そのものとマッチするものだと思っていたため非常に混乱しましたが、その回答をいただき理解できました。 \sそのもののマッチのさせ方は質問しなければ全く理解できなかったと思います。 本当に助かりました。ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問