Pythonの文字列検索は、「含まれるか」だけ知りたいなら in、位置が知りたいなら find(見つからないと -1)か index(見つからないと ValueError)、回数が知りたいなら count を使います。 先頭・末尾の判定は startswith と endswith、パターンで探すなら re モジュール、と目的ごとに道具が分かれています。

この記事では、7つの方法を「戻り値・見つからない時の挙動・用途」で並べた早見表を冒頭に置き、そのあとで1つずつコードと実行結果を示します。特に、if s.find(x): と書いたときに起きる誤判定、index の ValueError、すべての出現位置の取得(re.finditer)、大文字小文字を無視した判定(casefold)は、実際に動かした出力をそのまま載せています。

検証環境は Python 3.11.15 です。各メソッドの仕様は Python 3.14 の公式ドキュメント(組み込み型のページ)でも確認しました。記事内のコードは、特に断りがない限り次の文字列 s を使います。

s = "Python is fun. python is easy. PYTHON!"

文字列検索の早見表

方法 書き方 戻り値 見つからない時 向いている用途
in "is" in s True / False False 含まれるかの判定(if 文の条件)
not in "Java" not in s True / False True 含まれないことの判定
find s.find("is") 最初の位置(0始まり) -1 位置が欲しい、見つからないのも普通にありうる
rfind s.rfind("is") 最後の位置 -1 末尾側から探す(拡張子、最後の区切り)
index s.index("is") 最初の位置 ValueError 必ずあるはずの文字列の位置
rindex s.rindex("is") 最後の位置 ValueError index の末尾側版
count s.count("is") 出現回数 0 何回出てくるか(重なりは数えない)
startswith s.startswith("Python") True / False False 先頭の判定(タプルで複数指定可)
endswith s.endswith("!") True / False False 末尾の判定(拡張子など)
re.search re.search(r"p\w+n", s) Match オブジェクト None パターンで探す、最初の1件
re.finditer re.finditer("is", s) Match のイテレータ 空 すべての出現位置
re.findall re.findall("python", s, flags=re.I) 文字列のリスト 空リスト 一致した文字列の一覧・件数

上の表の実行結果です。

import re

s = "Python is fun. python is easy. PYTHON!"

print("is" in s, "Java" in s, "Java" not in s)
print(s.find("is"), s.find("Java"))
print(s.rfind("is"), s.rfind("Java"))
print(s.index("is"), s.rindex("is"))
print(s.count("is"), s.count("Java"))
print(s.startswith("Python"), s.endswith("!"))
print(re.search(r"p\w+n", s))
print([m.start() for m in re.finditer("is", s)])
print(re.findall("python", s, flags=re.I))
True False True
7 -1
22 -1
7 22
2 0
True True
<re.Match object; span=(15, 21), match='python'>
[7, 22]
['Python', 'python', 'PYTHON']

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「Python文字列検索 find・in・index・countの違い早見表」

どれを使うか迷ったときの判断表

知りたいこと 使うもの 理由
含まれるかどうかだけ in 結果が True / False で、if 文にそのまま書ける
最初に出てくる位置 find 見つからないときは -1 で、処理を続けやすい
必ずあるはずの位置 index ない場合に ValueError で気づける
最後に出てくる位置 rfind 末尾側から1回で探せる
何回出てくるか count 回数がそのまま返る
先頭・末尾が決まった文字列か startswith / endswith 位置を気にせず読みやすく書ける
すべての位置 re.finditer 位置つきで全件を取り出せる
大文字小文字を区別しない casefold してから in 両方をそろえてから比べる
数字3桁のようなパターン re.search 固定の文字列では表せない条件を書ける
複数の候補のどれかを含むか any(w in s for w in words) 候補のリストをそのまま回せる

公式ドキュメントの find の項にも、「find は位置を知る必要があるときだけ使い、部分文字列かどうかの確認には in 演算子を使う」という趣旨の注記があります。まず in で足りるかを考え、位置や回数が必要になったら find・index・count に進む、という順番で選ぶと迷いません。

含まれるかを判定する:in

「含まれるか」の判定は in がいちばん短く、読みやすい書き方です。

s = "Python is fun. python is easy. PYTHON!"

if "fun" in s:
    print("fun が含まれています")

if "Java" not in s:
    print("Java は含まれていません")
fun が含まれています
Java は含まれていません

複数のキーワードで判定する

any と all を組み合わせると、「どれか1つでも含む」「すべて含む」を1行で書けます。

words = ["Java", "fun", "easy"]

print(any(w in s for w in words))   # どれか1つでも含む
print(all(w in s for w in words))   # すべて含む
print([w for w in words if w in s]) # 含まれていたものだけ
True
False
['fun', 'easy']

in で知っておきたい3つの性質

性質 コード 結果
空文字列は常に含まれる "" in s True
大文字小文字は区別される "python" in "Python" False
文字列以外を左に置くと TypeError 1 in "123" TypeError
try:
    1 in "123"
except TypeError as e:
    print(type(e).__name__, e)
TypeError 'in <string>' requires string as left operand, not int

数値を探したいときは str(1) in "123" のように文字列へ変換します。

リストの in とは意味が違う

文字列の in は「部分文字列」を、リストの in は「要素そのもの」を探します。 同じ書き方でも結果が変わるので、変数が文字列なのかリストなのかを意識します。

tags = ["python", "sql"]

print("py" in tags)       # リスト:要素 "py" はない
print("python" in tags)   # リスト:要素 "python" がある
print("py" in "python")   # 文字列:部分文字列として含まれる
False
True
True

なお、リストには find メソッドがありません。tags.find("sql") は AttributeError: 'list' object has no attribute 'find' になります。リストで位置を知りたいときは tags.index("sql") を使います。

位置を調べる:find と rfind

find は、最初に見つかった位置を 0 始まりの整数で返し、見つからないときは -1 を返します。rfind は末尾側から探して、最後に見つかった位置を返します。

print(s.find("is"))        # 最初の位置
print(s.rfind("is"))       # 最後の位置
print(s.find("Java"))      # 見つからない
print(s.find("is", 8))     # 8文字目以降から探す
print(s.find("is", 0, 5))  # 0〜4文字目の範囲で探す
7
22
-1
22
-1

第2引数と第3引数は、スライスと同じ「開始位置」「終了位置(その手前まで)」です。count、index、startswith でも同じ形で範囲を指定できます。

見つけた位置を使って切り出す

位置がわかると、その前後を切り出せます。代入式(:=、Python 3.8 以降)を使うと、検索と判定を1行にまとめられます。

if (pos := s.find("fun")) != -1:
    print(pos)
    print(s[pos:pos + len("fun")])
    print(s[:pos], "|", s[pos + len("fun"):])
10
fun
Python is  | . python is easy. PYTHON!

「区切り文字の前と後ろに分けたい」だけなら、partition も便利です。位置を計算せずに3つ組で受け取れます。

print(s.partition("is"))
('Python ', 'is', ' fun. python is easy. PYTHON!')

if s.find(x): と書くと判定がずれる

find を if 文の条件にそのまま書くと、意図と逆の結果になることがあります。これはfind の戻り値が位置(整数)であり、True / False ではないためです。

s = "Python is fun. python is easy. PYTHON!"

for word in ["Python", "is", "Java"]:
    if s.find(word):
        print(word, "-> 真")
    else:
        print(word, "-> 偽")
Python -> 偽
is -> 真
Java -> 真
探した文字列 find の戻り値 if での扱い 実際に含まれるか
Python 0(先頭にある) 偽 含まれる
is 7 真 含まれる
Java -1(見つからない) 真 含まれない

Python では 0 が偽、0 以外の整数(-1 を含む)が真として扱われます。そのため、先頭で見つかった場合(0)が偽、見つからない場合(-1)が真という、ちょうど逆の判定になります。

直し方は2つあります。

# 直し方1:含まれるかだけなら in を使う
for word in ["Python", "is", "Java"]:
    print(word, word in s)

# 直し方2:find を使うなら -1 と比べる
for word in ["Python", "is", "Java"]:
    print(word, s.find(word) != -1)
Python True
is True
Java False
Python True
is True
Java False

見つからないまま -1 をスライスに使うと

もう1つ気をつけたいのが、-1 をそのまま添字やスライスに使うケースです。-1 は「末尾の1文字」を指す有効な添字なので、エラーにならずに処理が進みます。

print(s[s.find("Java"):])   # 見つからないのに末尾の1文字が取れる
print(s[:s.find("Java")])   # 末尾の1文字だけ欠けた文字列になる
!
Python is fun. python is easy. PYTHON

find の結果を位置として使う前に、必ず -1 かどうかを確認するか、次に説明する index を使って例外で気づけるようにします。

見つからないと例外になる:index

index は find と同じく最初の位置を返しますが、見つからないときに ValueError を送出します。

print(s.index("is"))

try:
    s.index("Java")
except ValueError as e:
    print(type(e).__name__, e)
7
ValueError substring not found

try を付けずに実行した場合は、この ValueError でプログラムがその場で止まります。

find と index の使い分け

観点 find index
見つかったとき 位置を返す 位置を返す
見つからないとき -1 を返す ValueError を送出
確認の書き方 if pos != -1: try と except ValueError
確認を忘れた場合 -1 のまま処理が進む その場で止まって気づける
向いている場面 見つからないことも普通にある検索 必ず含まれている前提の文字列
リストでも使えるか 使えない 使える(list.index)

「見つからないのは想定内」なら find、「見つからないのは想定外で、その先の処理を進めたくない」なら index、と考えると選びやすくなります。

見つからないときに None を返す関数にしておくと、呼び出し側で扱いやすくなります。

def position(text, sub):
    """sub の位置を返す。見つからないときは None。"""
    try:
        return text.index(sub)
    except ValueError:
        return None

print(position(s, "easy"))
print(position(s, "Java"))
25
None

回数を数える:count

count は、指定した文字列が何回出てくるかを整数で返します。見つからないときは 0 です。

print(s.count("is"))
print(s.count("Java"))
print("banana".count("a"))
print("banana".count("a", 2))      # 2文字目以降
print("banana".count("a", 2, 4))   # 2〜3文字目
2
0
3
2
1

count は重なりを数えない

count は、一度数えた部分とは重ならないように左から数えます。重なりも含めて数えたいときは、正規表現の先読み (?=...) を使います。

import re

print("aaaa".count("aa"))                    # 重ならない数え方
print(len(re.findall("(?=aa)", "aaaa")))     # 重なりも数える
print("banana".count("ana"))
print(len(re.findall("(?=ana)", "banana")))
2
3
1
2

空文字列を数えると「文字数 + 1」

print(len(s), s.count(""))
38 39

公式ドキュメントにも、空文字列を渡した場合は文字と文字の間の数、つまり「文字列の長さ + 1」を返すと書かれています。ユーザー入力をそのまま count に渡す場合は、空文字列でないことを先に確認しておくと安心です。

単語として数えたいとき

count は部分文字列を数えるので、cat を探すと concat や catalog の中の cat も数に入ります。単語として数えたいときは、正規表現の \b(単語の境界)を使います。

t = "cat concat catalog"

print(t.count("cat"))
print(re.findall(r"\bcat\b", t))
print("cat" in t.split())   # 空白で区切った単語の中にあるか
3
['cat']
True

先頭・末尾を判定する:startswith と endswith

「ある文字列で始まるか・終わるか」は、find の結果を 0 と比べるより、startswith と endswith のほうが意図がはっきり伝わります。

fn = "report_2026.csv"

print(fn.startswith("report"))
print(fn.endswith((".csv", ".tsv")))   # タプルで複数の候補
print(fn.startswith("2026", 7))        # 7文字目から始まるか
print("report.CSV".lower().endswith((".csv", ".tsv")))
True
True
True
True

複数の候補はタプルで渡します。 リストを渡すと次のエラーになります。

try:
    fn.startswith(["a", "b"])
except TypeError as e:
    print(e)
startswith first arg must be str or a tuple of str, not list

リストで持っている場合は fn.startswith(tuple(prefixes)) のように変換します。先頭や末尾を取り除きたいときは、Python 3.9 以降の removeprefix と removesuffix が使えます。

print(s.removeprefix("Python "))
is fun. python is easy. PYTHON!

すべての出現位置を取得する:re.finditer

find が返すのは最初の1件だけです。すべての位置が欲しいときは re.finditer を使うと、1行で書けます。

import re

s = "Python is fun. python is easy. PYTHON!"

print([m.start() for m in re.finditer("is", s)])
print([m.span() for m in re.finditer("python", s, re.IGNORECASE)])
[7, 22]
[(0, 6), (15, 21), (31, 37)]

Match オブジェクトからは、次の情報を取り出せます。

メソッド 意味 例(re.search(r"p\w+n", s) の場合)
m.group() 一致した文字列 python
m.start() 開始位置 15
m.end() 終了位置(その手前まで) 21
m.span() 開始と終了のタプル (15, 21)

記号を含む文字列は re.escape を通す

正規表現では、ピリオドやかっこなどの記号が特別な意味を持ちます。固定の文字列を探すときは re.escape で包むと、記号がそのままの文字として扱われます。

print(re.search("fun.", "fun!"))               # . が「任意の1文字」として働く
print(re.search(re.escape("fun."), "fun!"))    # ピリオドそのものを探す
print([m.start() for m in re.finditer(re.escape("."), s)])
<re.Match object; span=(0, 4), match='fun!'>
None
[13, 29]

正規表現を使わずに全位置を取る

find の開始位置をずらしながら繰り返す方法もあります。こちらは重なりも含めて見つけます。

def find_all(text, sub):
    """sub が出てくる位置をすべて返す(重なりも含む)。"""
    positions = []
    pos = text.find(sub)
    while pos != -1:
        positions.append(pos)
        pos = text.find(sub, pos + 1)
    return positions

print(find_all(s, "is"))
print(find_all("aaaa", "aa"))                            # 重なりを含む
print([m.start() for m in re.finditer("aa", "aaaa")])    # 重ならない
print([m.start() for m in re.finditer("(?=aa)", "aaaa")])# 先読みで重なりを含む
[7, 22]
[0, 1, 2]
[0, 2]
[0, 1, 2]
方法 重なり 特徴
re.finditer(re.escape(sub), text) 含まない 1行で書ける。終了位置も取れる
re.finditer("(?=" + re.escape(sub) + ")", text) 含む 先読みで重なりも拾う
find を繰り返す関数 含む re を使わずに書ける

n番目の位置を取る

def find_nth(text, sub, n):
    """n 番目(1始まり)の位置を返す。なければ -1。"""
    pos = -1
    for _ in range(n):
        pos = text.find(sub, pos + 1)
        if pos == -1:
            return -1
    return pos

print(find_nth(s, "is", 1), find_nth(s, "is", 2), find_nth(s, "is", 3))
7 22 -1

複数のキーワードの位置をまとめて調べる

keywords = ["fun", "easy", "Java"]

print({k: s.find(k) for k in keywords})

pattern = re.compile("|".join(map(re.escape, keywords)))
print([(m.group(), m.start()) for m in pattern.finditer(s)])
{'fun': 10, 'easy': 25, 'Java': -1}
[('fun', 10), ('easy', 25)]

複数行のテキストから行番号つきで探す

ログや CSV のような複数行のテキストでは、行ごとに in で調べると行番号を付けやすくなります。

text = """id,name,status
1,ノート,在庫あり
2,ペン,在庫なし
3,ファイル,在庫あり"""

for no, line in enumerate(text.splitlines(), 1):
    if "在庫あり" in line:
        print(no, line)

print(text.count("在庫あり"))
2 1,ノート,在庫あり
4 3,ファイル,在庫あり
2

文字列全体での位置から「何行目の何文字目か」を求めることもできます。

for m in re.finditer("在庫", text):
    line = text.count("\n", 0, m.start()) + 1
    col = m.start() - (text.rfind("\n", 0, m.start()) + 1)
    print(line, col)
2 6
3 5
4 7

ここでは count の範囲指定と rfind を組み合わせています。早見表のメソッドは、このように組み合わせて使えます。

大文字小文字を無視して検索する:casefold

in も find も count も、大文字と小文字を区別します。区別せずに探すときは、探す側と探される側の両方を casefold でそろえてから比べます。

s = "Python is fun. python is easy. PYTHON!"

print("python" in s.casefold())             # 含まれるか
print(s.casefold().count("python"))         # 回数
print(s.casefold().find("python", 1))       # 2件目以降の位置
print("PYTHON".casefold() in s.casefold())  # 探す側もそろえる
True
3
15
True

探すキーワードが変数に入っている場合は、キーワード側にも casefold を付けるのを忘れないようにします。

lower との違い

casefold は lower より踏み込んで文字をそろえます。公式ドキュメントでは、ドイツ語の小文字 ß が ss と同じものとして扱われる例が紹介されています。

print("straße".lower(), "straße".casefold())
print("STRASSE".lower() == "straße".lower())
print("STRASSE".casefold() == "straße".casefold())
straße strasse
False
True
方法 向いている場面
lower() 英数字だけを扱うとわかっている場合。表示用の小文字化
casefold() 比較・検索のためにそろえる場合。英語以外の文字が混ざる可能性がある場合
re.IGNORECASE 正規表現で探す場合。元の文字列の位置がそのまま取れる

位置が欲しいときは re.IGNORECASE が扱いやすい

casefold は文字数が変わることがあります(ß が ss になるなど)。そのため、casefold した文字列で調べた位置は、元の文字列の位置とずれる場合があります。

u = "Straße 12"
print(u.casefold().find("12"), u.find("12"))
8 7

元の文字列での位置が必要なときは、re.IGNORECASE(短縮形は re.I)を使うと、元の文字列に対する位置がそのまま返ります。

print([m.span() for m in re.finditer("python", s, re.IGNORECASE)])
print(re.findall("python", s, flags=re.I))
[(0, 6), (15, 21), (31, 37)]
['Python', 'python', 'PYTHON']

行のリストから大文字小文字を無視して探す

lines = ["INFO start", "ERROR disk full", "info done", "Error retry"]

print([i for i, line in enumerate(lines) if "error" in line.casefold()])
[1, 3]

全角と半角の違いは NFKC でそろえる

全角の英数字と半角の英数字は、casefold では同じになりません。全角・半角をそろえたいときは、unicodedata.normalize の NFKC を使います。

import unicodedata

title = "python入門"
print("python" in title)
print("python" in unicodedata.normalize("NFKC", title))
False
True

日本語の文字列でも、find や count はそのまま使えます。位置は文字単位で数えられます。

print("東京都港区".find("港"), "東京都港区".count("京"))
3 1

正規表現で検索する:re.search と使い分け

固定の文字列では表せない条件(数字が3桁、英字で始まる、など)は re モジュールで探します。

import re

print(bool(re.search(r"\d", s)))                      # 数字を含むか
print(re.search(r"(\w+) is (\w+)", s).groups())      # かっこで取り出す
print(bool(re.fullmatch(r"\d{3}-\d{4}", "123-4567"))) # 全体が形式に合うか
print(re.match("is", s))                              # match は先頭だけを見る
print(re.search(r"\bis\b", "this is").start(), "this is".find("is"))
False
('Python', 'fun')
True
None
5 2
関数 探す範囲 戻り値 用途
re.search 文字列全体で最初の1件 Match か None 含まれるか、最初の位置
re.match 先頭から一致するか Match か None 先頭の形式を確かめる
re.fullmatch 全体が一致するか Match か None 入力値の形式チェック
re.findall すべて 文字列のリスト 一致した文字列の一覧
re.finditer すべて Match のイテレータ 位置つきで全件

最後の行は、find が this の中の is(位置 2)を見つけるのに対し、\b を付けた正規表現は単語としての is(位置 5)を見つける例です。

re.search の戻り値は Match オブジェクトか None なので、if の条件にそのまま書けます(find と違い、見つからないときは None で偽になります)。

if re.search("fun", s):
    print("見つかりました")
見つかりました

固定の文字列を探すだけなら、in や find のほうが短く読みやすく書けます。 正規表現は、パターンが必要なとき、全位置が欲しいとき、大文字小文字を無視して位置を取りたいときに使う、と分けておくとコードがすっきりします。

None や bytes を検索するときの注意

外部から受け取った値は、文字列ではなく None や bytes になっていることがあります。どちらも TypeError になるので、検索の前に型をそろえます。

value = None
try:
    "a" in value
except TypeError as e:
    print(e)

data = b"cab"
print(b"ab" in data, data.find(b"ab"))   # bytes どうしなら検索できる
try:
    "ab" in data
except TypeError as e:
    print(e)

print("ab" in data.decode("utf-8"))       # str に変換してから探す
argument of type 'NoneType' is not iterable
True 1
a bytes-like object is required, not 'str'
True
受け取った値 そろえ方
None の可能性がある if text and key in text: のように、先に空でないことを確かめる
bytes(ファイルや通信の生データ) data.decode("utf-8") で str にするか、探す側を b"..." にする
数値 str(n) で文字列にしてから探す

よくあるエラーと直し方

エラー・症状 原因 直し方
ValueError: substring not found index で見つからなかった try と except ValueError で受ける。または find と -1 の比較にする
先頭にあるのに「ない」と判定される if s.find(x): と書いている if x in s: にする
ないのに「ある」と判定される 同上(-1 が真になる) if s.find(x) != -1: にする
TypeError: 'in <string>' requires string as left operand, not int 数値を in の左に置いた str(n) in s にする
TypeError: must be str, not int s.find(1) のように数値を渡した s.find(str(1)) にする
TypeError: argument of type 'NoneType' is not iterable 探される側が None if text and x in text: のように先に確認する
TypeError: a bytes-like object is required, not 'str' bytes の中を str で探した b"ab" in data にするか、data.decode() してから探す
AttributeError: 'list' object has no attribute 'find' リストに find を使った x in items や items.index(x) を使う
TypeError: startswith first arg must be str or a tuple of str, not list startswith にリストを渡した tuple(...) に変換する
大文字小文字が違って見つからない 区別されている 両方に casefold() を付ける。または re.I
. や ( を含む検索で結果がずれる 正規表現の記号として解釈された re.escape() を通す

書く前のチェックリスト

  • 知りたいのは「あるかないか」「位置」「回数」のどれか
  • find の結果を if にそのまま書いていないか(-1 と比べているか)
  • 見つからない場合の動きを決めたか(-1 で続ける/例外で止める)
  • 大文字小文字、全角半角をそろえる必要があるか
  • 探すキーワードが空文字列や None になる可能性はないか
  • 正規表現に渡す固定文字列を re.escape で包んだか

よくある質問

Q. find と index はどちらを使えばよいですか? A. 見つからないことが普通にありうる検索は find、必ず含まれている前提なら index が向いています。find は見つからないと -1 を返すので、位置として使う前に != -1 を確認します。index は見つからないと ValueError になるので、確認を忘れても -1 のまま処理が進むことがありません。含まれるかどうかだけなら、どちらでもなく in を使います。

Q. 文字列の中の全部の位置を取るにはどうすればよいですか? A. [m.start() for m in re.finditer(re.escape(sub), text)] が1行で書けて便利です。重なった出現("aaaa" の中の "aa" を 0、1、2 と数えるなど)も必要な場合は、find の開始位置をずらしながら繰り返す関数か、正規表現の先読み (?=...) を使います。

Q. 大文字小文字を区別せずに検索するには? A. 含まれるかの判定なら key.casefold() in text.casefold() のように両方をそろえます。元の文字列での位置が必要なら re.search(re.escape(key), text, re.IGNORECASE) を使うと、文字数のずれを気にせずに位置を取れます。

Q. in と find はどちらが速いですか? A. どちらも同じ種類の検索を行うため、選ぶ基準は速さより読みやすさです。含まれるかの判定は in、位置が必要なら find、と目的で選ぶのがおすすめです(速度の比較は今回の記事では扱っていません)。

まとめ

  • 含まれるかの判定は in。結果が True / False で、if 文にそのまま書ける
  • 位置は find(見つからないと -1)か index(見つからないと ValueError)。想定内か想定外かで選ぶ
  • if s.find(x): は先頭一致(0)が偽、見つからない(-1)が真になる。in か != -1 で書く
  • 回数は count。重なりは数えず、空文字列を渡すと「文字数 + 1」になる
  • 先頭・末尾は startswith と endswith。複数の候補はタプルで渡す
  • すべての位置は re.finditer。固定の文字列は re.escape で包む
  • 大文字小文字を無視するなら両方に casefold。位置が必要なら re.IGNORECASE

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「Python文字列検索 find・in・index・countの違い早見表」

株式会社RJCでは、Pythonの文字列検索のような基本の使い分けを仲間と学び合っています。こうした知識を共有しながら、日々技術を磨いています。

株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?