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

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

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

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

Q&A

0回答

986閲覧

pythonにて日本語のtxtファイル内の特定の文字列が含まれる行検索を行ったが、検索に引っかからない。

R_kun

総合スコア4

Python

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

0グッド

0クリップ

投稿2021/02/02 05:28

編集2021/02/02 05:56

前提・実現したいこと

pythonにて東京都港区の駅名を入力すると、東京港区の駅名が1行ずつ記載された「minatoku.txt」ファイルを検索し、入力した駅名が記載されている行数を返す関数を作成したいと考えております。

エラーは出力されずに終了するプログラムを作成できたのですが、駅名を変えても入力した区名が含まれるtxtファイルの行数+1を返すプログラムになっており、入力した駅名の検索が出来ていないことがわかりました。
下記の例ですと、32行目と返すはずが35行目までのtxtファイルを検索しきって、36行目を返してきます。なお入力で与えている変数を関数内に直書きすると、32行目を返してくれます。
(args1 = "三田"を関数内に記載すると、正しく「32」行目を返す。)

関数内に変数を直書きするとうまくいくので、
引数として与えている入力変数、直書きの値、txtから読み込んでいる値の文字コードに不整合が起き、違う値として認識されているため、検索に引っかからないのかと思いましたが、
全てstr型になっており、上手くいかない理由が見当たりません。。。

検索に引っかからない理由と対処方法を教えていただけると幸いです。
ファイル、変数の文字コードは以下の通りです。

引数で与えている入力データ「args1」(下記例だと三田):str
print(type(args1))
<class 'str'>

直書きした場合の入力データ「args1」(下記例だと三田):str
print(type(args1))
<class 'str'>

「minatoku.txt」から読み込んだデータ「src_data」
src_data:str
print(type(src_data))
<class 'str'>

東京港区の駅名が記載された「minatoku.txt」:utf-8
./input/minatoku.txt: utf-8 with confidence 0.99

★関数の呼び出し元の「teststationid.py」を追記いたしました。
ご確認、よろしくお願いいたします。

発生している問題・エラーメッセージ

# python3 teststationid.py 三田 三田 青山一丁目駅 ------ 赤坂駅 ------ 赤坂見附駅 ------ 赤羽橋駅 ------ 麻布十番駅 ------ お台場海浜公園駅 ------ 御成門駅 ------ 表参道駅 ------ 神谷町駅 ------ 外苑前駅 ------ 汐留駅 ------ 品川駅 ------ 芝浦ふ頭駅 ------ 芝公園駅 ------ 白金高輪駅 ------ 白金台駅 ------ 新橋駅 ------ 泉岳寺駅 ------ 高輪ゲートウェイ駅 ------ 高輪台駅 ------ 竹芝駅 ------ 田町駅 ------ 溜池山王駅 ------ 台場駅 ------ 大門駅 ------ 虎ノ門駅 ------ 虎ノ門ヒルズ駅 ------ 乃木坂駅 ------ 浜松町駅 ------ 日の出駅 ------ 広尾駅 ------ 三田駅 ------ モノレール浜松町駅 ------ 六本木駅 ------ 六本木一丁目駅 ------ 36

該当のソースコード

python

1def getstationid(args1): 2 import io,sys 3 sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8') 4 5 with open('./input/minatoku.txt', 'r', encoding='utf-8') as f1: 6      a = 1 7      x1 = 0 8      for src_data in f1: 9       print(src_data) 10       print("------") 11       if args1 in src_data: 12        break 13       else: 14        a = a +1 15      x1 = a 16 return x1

minatokutxt

1青山一丁目駅 2赤坂駅 3赤坂見附駅 4赤羽橋駅 5麻布十番駅 6お台場海浜公園駅 7御成門駅 8表参道駅 9神谷町駅 10外苑前駅 11汐留駅 12品川駅 13芝浦ふ頭駅 14芝公園駅 15白金高輪駅 16白金台駅 17新橋駅 18泉岳寺駅 19高輪ゲートウェイ駅 20高輪台駅 21竹芝駅 22田町駅 23溜池山王駅 24台場駅 25大門駅 26虎ノ門駅 27虎ノ門ヒルズ駅 28乃木坂駅 29浜松町駅 30日の出駅 31広尾駅 32三田駅 33モノレール浜松町駅 34六本木駅 35六本木一丁目駅

teststationidpy

1import sys 2import aisub 3 4args = sys.argv 5 6print(args[1]) 7 8stationid = aisub.getstationid(args[1]) 9 10print(stationid)

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

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

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

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

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

meg_

2021/02/02 05:36

teststationid.pyのコード全てを掲載された方が良いかと思います。
R_kun

2021/02/02 05:57

ご指摘ありがとうございます。掲載させて頂きました。
TakaiY

2021/02/02 08:12 編集

引数の文字コードがUTF-8でないというのがいちばんありそうです。 strというのは、文字列型を表わしているので、文字コードとは無関係です。 そのあたりをはっきりさせるために、作業しているOSと pythonのバージョンを追記してください。
bsdfan

2021/02/02 08:38

コマンドラインにコピペしたときなど、表示されないコードが紛れ込む場合があります。 print(len(sys.argv[1]) とか print([ord(c) for c in sys.argv[1]]) とかして確認してみてはどうでしょう。
R_kun

2021/02/02 10:22

>TakaiY様 ご確認痛み入ります。。。 centos7.9.2009 python3.6.8 docker 20.10.2.build2291f61上で動作させております。 操作はteratarm4.105(端末の設定で受信・送信ともにUTF-8) (今後質問する際は記載する様にします。必要な情報でした。) なお下記bsdfan様のアドバイスで文字数を計りましたが、引数の場合と直書きの場合で文字数が異なりました。 仰る通り文字列型は同じだが文字コードが異なる様に見えます。 (pyrhonで扱う日本語のstr型=UTF-8と思ってましたが、引数だからpythonの世界じゃないんですね。。。) >bsdfan様 アドバイスありがとうございます。以下を手打ちで入力しております。 pyと三田の間は半角です。 python3 teststion.py 三田 print(Len(args1))とした場合、 コマンドラインの引数の場合は6 直書の場合は2となりました。 またprint(Len(src_data))←「minatoku.txt」から読み込んだデータの場合は 文字数+1(三田駅なら4) となりました。 これはすごいヒントになりそうです。やはり認識しているものが違うから、検索に引っかからないんですね! >ご両名様 その後調べてみてはいるのですが、まだ解消方法がわからず、もしお分かりでしたら教えていただけると大変助かります。。。
ppaul

2021/02/02 10:53

プログラムに以下のコードを入れてください。 print(args[1].encode()) print(args[2].encode()) exit() そのあと、以下のコマンドを実行して下さい。 # python3 teststationid.py 三田 赤坂見附 これで何が表示されるかを教えてください。
TakaiY

2021/02/02 11:05

6文字ということは、たぶんbyte列になっているように思えます。「三田」をutf-8にすると、「\xe4\xb8\x89\xe7\x94\xb0」と6バイトでした。 ただ、こちらでubuntuで同じようのことをしてみても、そのようにはなりません。よくわからないですね。 bype列から文字列への変換は、.decodeでできるので、試してみるといいかもしれません。 また、文字数+1 なのは、最後に改行が入っているからでしょう。
R_kun

2021/02/02 11:10 編集

ppaul様 以下の通りとなりました。取り急ぎですいません。 # python3 teststationid.py 三田 赤坂見附 Traceback (most recent call last):   File "teststationid.py", line 10, in <module>     print(args[1].encode()) UnicodeEncodeError: 'utf-8' codec can't encode characters in position 0-5: surrogates not allowed teststation.pyは以下の通りです。 import sys import aisub args = sys.argv print(args[1].encode()) print(args[2].encode()) exit()
R_kun

2021/02/02 11:20 編集

すいません、下記は誤報でした。 decode()の()を忘れてました。変わらずUnicodeEncodeError: 'utf-8' codec can't encode charactersでした。 ppaul様 ソースを修正したところ、以下となりました。 # python3 teststationid.py 三田 赤坂見附 <built-in method encode of str object at 0x7f699b069500> <built-in method encode of str object at 0x7f699b0f09f0> # cat teststationid.py import sys import aisub import io, sys sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8") args = sys.argv print(args[1].encode) print(args[2].encode) exit()
TakaiY

2021/02/02 11:22

このエラーを見ると、入力されている文字列はutf-8ではありませんね。
bsdfan

2021/02/02 11:25

print([ord(c) for c in sys.argv[1]]) はどうなりますか?
R_kun

2021/02/02 11:46

bsdfan様 # python3 teststationid.py 三田 赤坂見附 三田 赤坂見附 [56548, 56504, 56457, 56551, 56468, 56496] [56552, 56501, 56484, 56549, 56477, 56450, 56552, 56486, 56 となりました。下記の意味はまだ理解できていないですが、python(サーバ?)での認識が見れて面白いです。。。 これは何の文字コードなのかとかわかるものなのでしょうか? print([ord(c) for c in sys.argv[1]]) TakaiY様 TakaiY様が最初に仰ってたことですね。。。 teratarmでの入力も文字コードが関係あるんですね。 この場合、encode、decodeし直して、引数をUTF-8に変換にするなどは出来るのでしょうか? >ご両名様 質問ばかりですいません。もしわかれば教えてください。
bsdfan

2021/02/02 12:23

ord()はその文字のユニコードでの値を返してくれます。 [56548, 56504, 56457, 56551, 56468, 56496] を 16進で書くと [dce4, dcb8, dc89, dce7, dc94, dcb0] なので、下位バイトは'三田'のUTF-8表現と一致していますね。 なんでこんなことになっているのかは、ちょっとわからないです。 想像では、dockerのpythonとのことなので、dockerのコンテナでちゃんとlocaleが設定されておらずC localeで動作しているとかではないのかな、と。
ppaul

2021/02/02 13:01

windows10 anacondaと、centos7.9.2009 anacondaでは、R_kunさんの期待通りの動きをしていることは確認しました。 dockerをやめて、他の環境に移行するのが一番手軽ですね。 しかし、どういう文字コードを使っているのかは興味深いところです。
R_kun

2021/02/05 11:14 編集

psdfan様、ppaul様 ご連絡が遅くなり、申し訳ないです。文字コードを勉強し直し、decodeしたりlocaleの設定を変えたりとしましたが、解消できませんでした。localeを日本語の設定しても日本語表記ならず、docker+centosの私の環境がどうもおかしい様です。 対応としては引数をテキストから読み込むことで、標準入力の絡みを無くして動作させることにしました。 ご回答、本当にありがとうございました。 今後日本語を標準入力する場合は、環境を変えるしかなさそうですね。 Takai Y様もご回答誠にありがとうございました。
R_kun

2021/02/05 11:17

ベストアンサーは皆様の回答が参考になったため、選び難いですが、実機での確認を頂いて、解決策をご提示頂いたPPaul様とさせて頂きたいと存じます。 PPaul様 回答として頂いた上記のメッセージを投稿いただけますか? お手間な様でしたら、頃合いを見て、自己解決で投稿するので、無視いただいて構いません。
ppaul

2021/02/05 11:30

ご連絡、ありがとうございます。 今回は、大勢で考えても原因にたどり着けなかったので、もやもやしたものが残ります。 自己解決で投稿していただくようお願いします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.46%

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

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

質問する

関連した質問