スナックelve 本店

バツイチ40代女の日記です

正規表現のチートシート

経緯

snack.elve.club

昔の記事↑に、この記事も追加してみない? みたいなメールが来た。英語で(´;ω;`)ウッ…

 

PCWDLD.com のMarc Wilson-sanからだ。追加提案されたのは下記の記事。PythonRegExチートシートPythonでの正規表現の一覧ですね。

www.pcwdld.com

 

冒頭の記事はツイートから体重抽出してるだけだから、チートシートを日本語に訳して載せてもいい? って聞いたら快諾された。藪蛇感w
基本的にグーグル先生による翻訳です。

PythonRegExチートシート

https://www.pcwdld.com/wp-content/uploads/Python-RegEx-Cheat-Sheet-730x480.jpg


正規表現は、文字列内の文字の組み合わせを照合するために使用されるパターンです。これらは、Pythonプログラミング言語で、指定されたテキストパターンを検索したり置換したりするのに便利です。Pythonには、Python正規表現を完全にサポートするREというモジュールがあります。簡単に言うと、Python正規表現は、複雑な文字列照合機能のパターンを定義する一意の文字シーケンス(処理する順番? 非反復配列?)です。

このPythonRegExチートシートには、ネットワークまたはシステム管理者がクイックリファレンスとして使用できる最も一般的に使用される正規表現が示されています。

Basic Characters(基本記号)

ここでは、単純な完全一致を実行するために使用されるいくつかの基本的な文字を示します。

Characters Explanation
a 正確に1つの文字に一致します。
ab 文字列abに一致します。
a|b aまたはbに一致します。aが一致した場合、bは残ります。
$ 文字列の終わりに一致します。
i ケースを無視します。
s 改行も含め、すべてに一致します。
u Unicode文字クラスに一致します。

x

Verbose


スペースとコメントを許可します。

re.VERBOSE

^ 文字列の先頭に一致します。
* 0回以上の繰り返しに一致します。
+ 1回以上一致します。
? ゼロまたは1回一致します。
{a,b} a回から b 回まで繰り返したもの。bに近い回数
{a,} 少なくとも一度は一致します。
{,b} b回まで一致します。
{a} 正確に一致します。
{a,b}? a回から b 回まで繰り返したもの。aに近い回数

特殊シーケンス(クラス)

クラスは、文字のセットを定義します。これは、文字通りの一致の後の最も基本的な正規表現の概念です。これにより、1つの小さな文字シーケンスがより広範な文字セットと一致します。

Class 説明
\d 0〜9の数字に一致します。
\D 数字以外のすべてに一致します。
\w az、AZ、0-9、およびアンダースコア(_)を含む英数字に一致します。
\W Unicode単語文字ではなく、任意の文字に一致します。
\s 空白文字に一致します。
\S 空白以外の文字に一致します。
\n 改行文字に一致します。
\t タブ文字に一致します。
\b 単語の最初または最後でのみ、空の文字列に一致します。*1
\Z 単一行モードか複数行モードかに関係なく、文字列の絶対的な終わり
\A 単一行モードか複数行モードかに関係なく、文字列の絶対的な先頭

文字セット(集合)

集合は、角括弧で囲まれた文字のセットです。Python正規表現は、集合内のいくつかの文字のうちの1つと一致します。

Sets 説明
[a-z] 任意の小文字のASCII文字に一致します。
[xyz] x,y,zのいずれかに一致します。
[x\-z] x,–,zに一致します。
[-x] x,–に一致します。
[a-d0-9] aからdまたは0から9の文字に一致します。
[^xy4] x,y,4以外の文字に一致します。
[(+*)] (,+,*,)に一致します。*2
[0-5][0-9] 00から59までの任意の2桁の数字に一致します。
[^ab5] ^を追加すると,セット内のすべての文字が除外されます。ここでは,a,b,5以外の文字と一致します。

Regular Expression(RE) モジュール関数

Pythonには、正規表現を操作するために使用されるreという組み込みモジュールがあります。reモジュールは、文字列で一致するものを検索できるようにする一連の関数を提供します

RE Functions 説明
re.Match 正規表現パターンを検索し、最初に出現したものを返します。
re.search 正規表現パターンと文字列を受け取り、文字列内でそのパターンを検索します。一致オブジェクトかNoneを返します。
re.fullmatch 文字列全体がパターンに一致する場合にのみ、一致オブジェクトを返します。それ以外の場合は、Noneを返します。
re.compile 正規表現パターンをパターンオブジェクトに結合して、パターンマッチングに使用できます。また、パターンを書き直さずに再度検索するのにも役立ちます。
re.sub 文字列を置換します。検索文字列に正規表現パターンが使え、置換後の文字列に関数なども使えます。re.sub
re.escape 英数字以外のすべてがバックスラッシュされた文字列を返します。これは、正規表現のメタ文字が含まれている可能性のある任意のリテラル文字列に一致させる場合に役立ちます。
re.split 文字列を複数の区切り文字で分割します。
re.findall 文字列のリストとして、文字列内の重複しないパターンの一致をすべて返します。
re.subn sub同様置換。タプル*3 (new_string、 number_of_subs_made) を返します。

Python正規表現RegEx)の例

このセクションでは、実際のP​​ython正規表現の例をいくつか紹介します。

IPアドレスの種類を見つける

ここでは、正規表現を使用して、指定されたIPアドレスIPv4IPv6、またはなしのいずれであるかを確認するPythonプログラムを作成します。

nano checkip.py

次のコードを追加します。

import re
ipv4 = '''^(25[0-5]|2[0-4][0-9]|[0-1]?[0-9][0-9]?)\.(
25[0-5]|2[0-4][0-9]|[0-1]?[0-9][0-9]?)\.(
25[0-5]|2[0-4][0-9]|[0-1]?[0-9][0-9]?)\.(
25[0-5]|2[0-4][0-9]|[0-1]?[0-9][0-9]?)$'''
ipv6 = '''(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|
([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:)
{1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1
,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}
:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{
1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA
-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a
-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0
-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,
4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}
:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9
])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0
-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]
|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]
|1{0,1}[0-9]){0,1}[0-9]))'''
def find(Ip):
    if re.search(ipv4, Ip):
        print("IPv4")
    elif re.search(ipv6, Ip):
        print("IPv6")
    else:
        print("None")
# Driver Code
if __name__ == '__main__' :
# Enter the Ip address
    Ip = "192.168.0.100"
find(Ip)

ファイルを保存して閉じ、次のコマンドでプログラムを実行します。*4

python3 checkip.py

上記のコードで指定されたIPアドレス(192.168.0.100)がIPv4なので、次の出力が得られるはずです。

IPv4
コマンドプロンプトで実行したらこんな感じ

f:id:elve:20211009095605p:plain

指定されたIPv4アドレスの予約有無チェック

指定されたIPアドレスが予約されているかどうかを確認します。一部のIPアドレスは、実験および研究目的で予約されています。IPアドレス範囲240.0.0.0– 255.255.255.254は、調査目的で予約されています。

予約済みのIPアドレスを確認するための新しいファイルを作成しましょう。(上で作ったcheckip.pyも必要です)

nano checkreservedip.py

次のコードを追加します。

from ipaddress import ip_address
def reservedIPAddress(IP: str) -> str:
    return "Reserved" if (ip_address(IP).is_reserved) else "Not Reserved"

if __name__ == '__main__' :

    # Not Reserved
    print(reservedIPAddress('192.168.0.123'))

    # Reserved
    print(reservedIPAddress('240.0.0.20'))

ファイルを保存して閉じてから、次のコマンドを使用してこれを実行します。

python3 checkreservedip.py

次の出力が得られるはずです。

Not Reserved
Reserved

これは、IPアドレス192.168.0.123が予約されておらず、IPアドレス240.0.0.20が予約されていることを意味します。

コマンドプロンプトで実行したらこんな感じ

f:id:elve:20211009100654p:plain

IPアドレス有効性チェック

この例では、指定されたIPアドレスが有効かどうかをテストします。

まず、test.pyファイルを作成します。

nano test.py

次のコードを追加します。

import re
k = 0
while k < 5 :
    i = input("\nEnter Ip address : ")
    ip = re.match("^([1][0-9][0-9].|^[2][5][0-5].|^[2][0-4][0-9].|^[1][0-9][0-9].|^[0-9][0-9].|^[0-9].)([1][0-9][0-9].|[2][5][0-5].|[2][0-4][0-9].|[1][0-9][0-9].|[0-9][0-9].|[0-9].)([1][0-9][0-9].|[2][5][0-5].|[2][0-4][0-9].|[1][0-9][0-9].|[0-9][0-9].|[0-9].)([1][0-9][0-9]|[2][5][0-5]|[2][0-4][0-9]|[1][0-9][0-9]|[0-9][0-9]|[0-9])$",i)
    k = k + 1
    if ip:
        print ("\n=====================")
        print ("Valid IP address")
        print ("=====================")
        break
    else :
        print ("\nInvalid IP")
else :
    print ("\nAllowed Max 5 times")

ファイルを保存して閉じてから、次のコマンドを使用してこれを実行します。

python3 test.py

IPアドレスを入力するように求められます

Enter Ip address: 192.168.0.111

任意のIPアドレスを入力し、Enterキーを押すと次の出力が得られます。

=====================
Valid IP address
=====================

今度は無効なIPアドレスを指定しましょう。次の結果が得られます。

Enter Ip address: 10.123.342.255
Invalid IP
コマンドプロンプトで実行したらこんな感じ

f:id:elve:20211009101600p:plain
f:id:elve:20211009101902p:plain
有効なIP入れるまで終わらないw あ、エラー5回で終わるか。

メールアドレスの有効性チェック

この例では、指定された電子メールアドレスが有効かどうかを確認します。
次のコマンドを使用してtest.pyファイルを作成しましょう。(上のファイルに上書きかな?)

nano test.py

次のコードを追加します。

import re
input_string = input("Enter Email address : ")
regex_pattern = r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b'

result = bool( re.match( regex_pattern, input_string))

if (result):
    print ("Valid Email address")
else:
    print ("Invalid Email address")

ファイルを保存して閉じてから、次のコマンドでこれを実行します。

python3 test.py

以下に示すように、電子メールアドレスを提供するように求められます。

Enter Email address : hitjethva@gmail.com

メールアドレスを入力してEnterキーを押します。指定された電子メールアドレスが有効な場合、次の結果が得られるはずです。

Valid Email address
コマンドプロンプトで実行したらこんな感じ

f:id:elve:20211009102418p:plain

システムのホスト名とIPアドレス出力

(なんかだんだん出力結果貼れない感じになってきたw 正規表現関係ないですよねぇぇぇぇ!?w おそらく元記事ひな形の残りwww)
この例では、システムのIPアドレスとホスト名を出力します。
次のコマンドを使用してtest.pyファイルを作成しましょう。

nano test.py

次のコードを追加します。

import socket
hostname = socket.gethostname()
IPAddr = socket.gethostbyname(hostname)
print("Your System Hostname is:" + hostname)
print("Your System IP Address is:" + IPAddr)

ファイルを保存して閉じてから、次のコマンドでこのスクリプトを実行します。

python3 test.py

次の出力が得られるはずです。

Your System Hostname is:newpc
Your System IP Address is:127.0.0.1です。

リモートホストの開いているポートスキャン

この例では、リモートホストをスキャンし、開いているすべてのポートを印刷します。

次のコマンドを使用して、test.pypythonスクリプトを作成しましょう。

nano test.py

次のコードを追加します。

from socket import *
import time
startTime = time.time()

if __name__ == '__main__':
    target = input('Enter the host to be scanned: ')
    t_IP = gethostbyname(target)
    print ('Starting scan on host: ', t_IP)

    for i in range(50, 500):
        s = socket(AF_INET, SOCK_STREAM)

        conn = s.connect_ex((t_IP, i))
        if(conn == 0) :
            print ('Port %d: OPEN' % (i,))
            s.close()
            print('Time taken:', time.time() - startTime)

ファイルを保存して閉じてから、次のコマンドを使用して上記のスクリプトを実行します。

python3 test.py

以下に示すように、リモートホストIPアドレスを入力するように求められます。

Enter the host to be scanned: 172.20.10.3

IPアドレスを入力し、Enterキーを押します。次の結果が得られます。

Starting scan on host: 172.20.10.3
Port 80: OPEN
Port 111: OPEN
Port 139: OPEN
Port 445: OPEN
Time taken: 1.1808812618255615

結論

上記のチートシートに、最も一般的に使用されるすべてのPython正規表現のリストと実際の例を示しました。クイックリファレンスとしてご利用いただければ幸いです。

日本語でできるかな?

疑似個人情報データ生成サービスでダミーデータを30件作りました。

import re
dStr="連番,氏名,氏名(カタカナ),氏名(ローマ字),性別,郵便番号,住所1,住所2,生年月日,年齢,1,鳥居 紫,トリイ ユカリ,Torii Yukari,F,849-1206,佐賀県,杵島郡白石町,1986/7/4,35,2,池谷 優,イケタニ マサル,Iketani Masaru,M,634-0043,奈良県,橿原市,1967/3/31,54,3,及川 孝男,オイカワ タカオ,Oikawa Takao,M,639-2162,奈良県,葛城市,1978/2/2,43,4,笠井 敏幸,カサイ トシユキ,Kasai Toshiyuki,M,039-1525,青森県,三戸郡五戸町,1969/4/17,52,5,西原 柚子,ニシハラ ユズ,Nishihara Yuzu,F,299-4321,千葉県,長生郡長生村,1989/1/9,32,6,本田 安奈,ホンダ アンナ,Honda Amna,F,106-0045,東京都,港区,1962/9/23,59,7,岸田 美姫,キシダ ミキ,Kishida Miki,F,563-0031,大阪府,池田市,1985/7/5,36,8,永瀬 堂下,ナガセ ドウシタ,Nagase Doushita,F,206-0041,東京都,多摩市,1998/8/20,23,9,野沢 永二,ノザワ エイジ,Nozawa Eiji,M,919-1525,福井県,三方上中郡若狭町,2000/7/24,21,10,横溝 美南,ヨコミゾ ミナミ,Yokomizo Minami,F,071-0714,北海道,空知郡中富良野町,1971/3/19,50,11,堀越 和之,ホリコシ カズユキ,Horikoshi Kazuyuki,M,893-0057,鹿児島県,鹿屋市,1969/10/2,52,12,藤村 一司,フジムラ カズシ,Fujimura Kazushi,M,904-1203,沖縄県,国頭郡金武町,1999/11/5,21,13,小坂 文香,オサカ フミカ,Osaka Fumika,F,699-3672,島根県,益田市,1993/11/23,27,14,平林 瑞穂,ヒラバヤシ ミズホ,Hirabayashi Mizuho,F,872-0862,大分県,宇佐市,1991/11/20,29,15,前田 和弘,マエダ カズヒロ,Maeda Kazuhiro,M,889-0504,宮崎県,延岡市,1968/7/26,53,16,堀越 彩葉,ホリコシ イロハ,Horikoshi Iroha,F,963-7763,福島県,田村郡三春町,1977/12/24,43,17,八木 優依,ヤギ ユイ,Yagi Yui,F,885-0041,宮崎県,都城市,1991/11/30,29,18,吉川 利恵,ヨシカワ リエ,Yoshikawa Rie,F,942-0206,新潟県,上越市,1962/10/13,58,19,芳賀 勇吉,ハガ ユウキチ,Haga Yuukichi,M,927-0054,石川県,鳳珠郡穴水町,1964/11/7,56,20,竹村 深雪,タケムラ ミユキ,Takemura Miyuki,F,639-3804,奈良県,吉野郡下北山村,1971/3/24,50,21,熊田 香凛,クマダ カリン,Kumada Karin,F,412-0028,静岡県,御殿場市,1971/11/16,49,22,菅谷 洋,スガヤ ヒロシ,Sugaya Hiroshi,M,135-0053,東京都,江東区,1988/12/25,32,23,村松 花梨,ムラマツ カリン,Muramatsu Karin,F,636-0012,奈良県,北葛城郡王寺町,1964/5/30,57,24,五味 瑞姫,ゴミ ミズキ,Gomi Mizuki,F,922-0005,石川県,加賀市,1980/7/13,41,25,梅本 竹雄,ウメモト タケオ,Umemoto Takeo,M,709-2135,岡山県,岡山市北区,1965/5/19,56,26,塚越 花梨,ツカゴシ カリン,Tsukagoshi Karin,F,606-0013,京都府,京都市左京区,1999/3/9,22,27,甲斐 寿,カイ ヒサシ,Kai Hisashi,M,739-1106,広島県,安芸高田市,1997/9/18,24,28,佐野 茂男,サノ シゲオ,Sano Shigeo,M,537-0012,大阪府,大阪市東成区,1964/3/2,57,29,山形 和恵,ヤマガタ カズエ,Yamagata Kazue,F,942-0154,新潟県,上越市,1961/11/14,59,30,西村 慶治,ニシムラ ケイジ,Nishimura Keiji,M,701-1464,岡山県,岡山市北区,1978/10/2,43"

tdfk=',[^,]+[都道府県],'
t=',[^,]+都,'
d=',[^,]+道,'
f=',[^,]+府,'
k=',[^,]+県,'

result0 = re.findall(tdfk, dStr)
result1 = re.findall(t, dStr)
result2 = re.findall(d, dStr)
result3 = re.findall(f, dStr)
result4 = re.findall(k, dStr)
print("{0}件の情報があり、そのうち".format(len(result0)))
print("{0}件が都民".format(len(result1)))
print("{0}件が道民".format(len(result2)))
print("{0}件府民".format(len(result3)))
print("{0}件県民です。".format(len(result4)))

結果は

c:\python>chkaddress.py
SyntaxError: Non-UTF-8 code starting with '\xe6' in file C:\python\chkaddress.py on line 2, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details

ファイルをBOM付きのUTF-8で上書き保存して(;^_^A
f:id:elve:20211009114440p:plain
おけ!

*1:ダブルコーテーション、バックスペース説あり

*2:集合の中では、特殊文字はその特殊な意味を失います。

*3:配列状のオブジェクト?

*4:Pythonインストールしてパスが通ってるところにメモ帳でcheckip.py作って保存したほうが楽かも