Pythonプログラミングでファイルを検索する方法

このQ&Aのポイント
  • Pythonのファイル操作で、指定したファイルをオープンし、キーワードを検索する方法について解説します。
  • ファイルを読み込み、改行を削除した後、指定したキーワードを検索します。一致する文字の位置が分かった後は、特定のパターンで次々と文字を取得していきます。
  • AとBの特定のパターンで文字を取得するプログラムを作成する方法についてご教示ください。
回答を見る
  • ベストアンサー

行き詰ってます。。

'ファイルをオープン' with open(target_file) as f: lines = f.readlines() '改行を削除' lines_strip = [line.strip() for line in lines] lines_strip = "".join(lines_strip) '検索' keyword = input() position = lines_strip.find(keyword) #ここで、keywordと一致する文字の場所が分かる。 ここからですが、その後、A xxx A ddd A ccc A vvv B zzz と続きます。 ※実現したいこと。 A xxx A ddd A ccc A vvv B zzz Bを検出したら終わり。というプログラムを記載したいのですが、 どのように書けばよいでしょうか?

  • Python
  • 回答数5
  • ありがとう数6

質問者が選んだベストアンサー

  • ベストアンサー
  • asciiz
  • ベストアンサー率70% (6641/9408)
回答No.5

>読み込むテキストファイルデータは、 (中略) >keywordは、input()で<>内の数値入力を想定してます。 ふむ、そうすると、単純な一重ループで処理するのは少々面倒ですね。 お望みの処理をするのに、いくつかのやり方があります。 ●方法1 入力された数字文字列(例:「100」なら「<100>」の行)を見つけるまで、読み飛ばす(行を読むだけで何もしない)。 該当行を見つけたら、次の処理に進む。 次の処理(ループ): 一行読んで、先頭文字が「<」でなければ、出力する。 「<」が出てきたら終了。 万が一、ファイル終端に達してしまったら、強制終了。 ●方法2 「見つけた」フラグ(変数) find=0 にしておく。 処理ループ: 一行読む。ただし読めない(ファイル末)ならば終了。 「見つけた」フラグが1のときに、先頭文字が「<」だったら、プログラム終了。そうでなければ、出力する。 先頭文字が「<」だったら、入力と比較して、一致したら「見つけた」フラグを1にする。 (処理ループ先頭へ) ●方法3 「<xxx>」から、次の「<xxx>」までの間を一気に読み込み、保持しておく。 「<xxx>」が入力値と一致すれば、読み込んだ数行を出力して終了。 そうでなければ破棄し、次のブロックを読みに行く。 ---- こんな感じでしょうか。 どの方法でも、結果は得られるでしょう。 なお、あなたの考えていたこちらの部分、 >Bを検出したら終わり。というプログラムを記載したいのですが、 サンプルデータでは、B で終わっていないブロックがあります。そのため、あなたの想定したプログラムをそのまま組んでしまうと、一度該当部を見つけた後、延々とデータを出力し続け、次に先頭Bが見つかるまで(あるいはファイル末まで)止まらないという動作をしてしまうでしょう。 なので上記では、「<xxx>」が処理したい区切りだ、という考えにしました。 どの方法も多少長くなるでしょうけど、組んでみてください。 まあ「方法1」が一番単純かと思います。 「方法2」はフラグ管理が面倒ですが、短くはなるでしょう。(でも極端に短いプログラムは読みにくい(理解しにくい)ことも多く、短さにこだわる必要はありません。) 「方法3」は、複数行の保持に「リスト」を使うと良いかもしれません。それはそれでプログラミングの練習になります。

the-man
質問者

お礼

誠に、ありがとうございます。 方法1で考えてみたいと思ってます。 が、先頭が必ず<とならない場合もあるのですが、100は確定です。 その場合は、findallを使うのでしょうか?? それとも、適した関数があるのでしょうか?

その他の回答 (4)

  • notnot
  • ベストアンサー率47% (4848/10262)
回答No.4

> #これだとループを抜けれないのが不明・・・。 何故私の書いた回答を無視するのでしょうか? #while True: # print(lines_strip) # if (lines_strip == "B"): #これだとループを抜けれないのが不明・・・。 # break ↑は、一体何を目的としたコードでしょうか?全く意味不明です。 > ここにpositionが10以降という何かがいると思ってます。 「positionが10以降」というのは、質問文中に何も書かれていないのですが、どういう意味なんでしょうか?10以降なら何??

the-man
質問者

お礼

ご回答が遅くなり申し訳ありません。

the-man
質問者

補足

読み込んだテキストデータから、keywordと一致した箇所のデータだけを抽出して表示したいと考えています。 keywordと一致した箇所の要素をlines_strip[10]と想定しました。 説明不足で誠に申し訳ありません。

回答No.3

文字列の先頭を比較したいのであれば、startswithを使うべきかと。

the-man
質問者

お礼

当初、startswithで考えていましたが、やりたいことを実現することに 沿わないのかなと思い、使用をやめました。 ありがとうございます。

  • asciiz
  • ベストアンサー率70% (6641/9408)
回答No.2

うーん、読み込むファイルはどんなデータなのでしょうか? そしてkeywordとして、どんな入力をしていますか? ># if (lines_strip == "B"): #これだとループを抜けれないのが不明・・・。 ここの疑問からすると、「文字列の先頭文字で判別したい」という話でしょうか。 lines_strip には、例えば、"B zzz" という文字列が入ってるんですから、"B" とは一致しません。 なのでループ脱出できません。 ここで、pythonには、部分文字列を取り出す方法があります。 正確に言うと、リスト(配列)の一部分を取り出す書き方です。 > リスト値 [ 開始インデックス : 終了インデックス+1 ] これを例えば、"abcdefg" という文字列で使うと、"abcdefg"[2:5] と書いたとき、インデックス2の"c"から、インデックス4の"e"までを取り出した"cde"という文字列になります。※インデックス番号は0が先頭であることに注意 なので先頭文字で判別したい場合、 if (lines_strip[0:1] == "B"): こんな風に書けばループ脱出できるのではないかと。

the-man
質問者

補足

うーん、読み込むファイルはどんなデータなのでしょうか? そしてkeywordとして、どんな入力をしていますか? ⇒読み込むファイルは、テキストファイルを想定してます。  読み込むテキストファイルデータは、 <100>  A xxx  A ddd  A ccc  A vvv  B zzz <200>  A xx1  A dd1  A cc1  A vv1  A zz1 <300>  A 3xx  A 3dd  A 3cc  A 3vv  A 3zz  keywordは、input()で<>内の数値入力を想定してます。

  • notnot
  • ベストアンサー率47% (4848/10262)
回答No.1

while True: でループにして、if keyword == "B": で breakする。

the-man
質問者

補足

別のスレを立てるべきかもしれませんが、 position = lines_strip.find(keyword) #ここでpositionが10とします。 ’’’ ここにpositionが10以降という何かがいると思ってます。 ’’’ #while True: # print(lines_strip) # if (lines_strip == "B"): #これだとループを抜けれないのが不明・・・。 # break 中々、難しく困ってます。。

関連するQ&A

  • さっぱり分からず困ってます。。

    読み込むテキストファイルは下記のとおりです。 <100>  A xxx  A ddd  A ccc  A vvv  B zzz //200//  A xx1  A dd1  A cc1  A vv1  A zz1 ・300  A 3xx  A 3dd  A 3cc  A 3vv  A 3zz 上記のテキストファイルから、100,200,300のキーワードで該当箇所から 次行を表示するプログラムを考えています。 下記のプログラムで実行すると、取得できるのですが、何度も繰り返し出力します。 1回で良いのですが、何度も繰り返す処理を記載しているつもりが無いのに、何故繰り返すのか意味不明で困ってます。 どうすれば、修正できるでしょうか。。 import re def extract_text_in_file(filepath, pattern_prev, pattern_next): '空のリスト生成' extracted_text_array = [] '抽出したい範囲' pattern = pattern_prev + '(.*)' + pattern_next 'ファイルオープン' with open(filepath) as f: lines = f.readlines() '改行削除、文字列に変換' lines_strip = [line.strip() for line in lines] lines_strip = "".join(lines_strip) '文字列lines_stripから抽出範囲を取得し、リストに追加' for i in lines_strip: tmp_extracted_text_array = re.findall(pattern, lines_strip) extracted_text_array.extend(tmp_extracted_text_array) return extracted_text_array path = 'C:\\Users' file_name = '/' + '***.txt' target = path + file_name pa_prev = '100' pa_next = 'B' x = extract_text_in_file(target,pa_prev,pa_next) print(x)

  • エラーの原因が分からず困ってます。

    下記のmatchのところで、エラー(TypeError: expected string or bytes-like object)が出て原因が分からず困ってます。 'ファイルをオープン' with open(target_file) as f: lines = f.readlines() '改行を削除' lines_strip = [line.strip() for line in lines] print(lines_strip)  keyword = input()  match = re.findall(keyword,lines_strip)

  • SQL 複数条件を設定

    使用言語はjavaで処理しており、 SQL Server2005にて下記のようなテーブル(T_Kekka)があります。    ID   a-1   a-2   b-1   b-2   c-1   c-2     ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄    1   bbb   aaa   ddd    ccc   eee   fff       2   ggg   bbb   ccc     hhh   iii    jjj       3   bbb   mmm   ddd   ccc   fff    eee       4   bbb   aaa   ccc    ddd   qqq   rrr       5   zzz   sss   ttt     ccc   vvv   xxx       6   zzz   aaa   ttt     ccc   vvv   fff       7   zzz   zzz   zzz     zzz   zzz    zzz       8   qqq   rrr   ccc     ddd   fff    eee    検索する値は下記の通りです。 検索値 |a-1|a-2|b-1|b-2|c-1|c-2|  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ |aaa|bbb|ccc|ddd|eee|fff| 期待値としては、aはaのグループで検索、bはbのグループで検索、cはcのグループで検索をし、 一致個数の多い順に出力したいと考えております。(理想は下記のような感じです。) また、グループ内であれば逆転していてもOKです。 (例えばID:1のaグループのような感じです。) *1 一致数が同じ場合はcグループの数が多いデータが最優先となり、その他はID順になります。 期待値    ID   a-1   a-2   b-1   b-2   c-1   c-2   一致数  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄    1   bbb   aaa   ddd   ccc   eee   fff     6    3   bbb   mmm   ddd   ccc   fff    eee    5    8   qqq   rrr    ccc   ddd   fff    eee    4・・・*1    4   bbb   aaa   ccc   ddd   qqq   rrr     4    6   zzz   aaa   ttt    ccc   vvv    fff     3    2   ggg   bbb   ccc   hhh   iii     jjj      2    5   zzz   sss   ttt    ccc   vvv    xxx     1    7   zzz   zzz   zzz    zzz   zzz    zzz     0 知識不足のため私には複雑すぎて悩んでいる状況なので、 どなた様か知識がある方にご教授願いたく思います。 また、まだテスト段階なので現状のようなテーブル構造にしてしまいましたが、 他のテーブル構造の方がデータが抽出しやすかったり、レスポンスがいい場合がありましたら、 ご教授いただけると助かります。 説明が分かりづらく表が見づらくて申し訳ございませんが、 宜しくお願い致します。

  • シェルスクリプトにてファイルの結合

    お世話になります。 ある3つのファイルfile1 file2 file3 の内容が file1が 111 222 333 file2が aaa ddd bbb eee ccc fff file3が xxx yyy zzz という内容を file4に 111 aaa ddd xxx 222 bbb eee yyy 333 ccc fff zzz という具合に横に結合させて出力させたいのですが どうしていいか分かりません。 sedとかawkを使えばいけそうなんですが 分かる方いらっしゃいませんか??? 宜しくお願いいたします。

  • ExcelのVBAでの複数階層からのフォルダ名の取得

    ExcelのVBAでの複数階層からのフォルダ名の取得 下記階層に対して以下の処理をExcelのVBAで行うにはどしたら良いか、 申し訳ありませんが、どうか教えて頂きたく思います。 C:\test1   ├\aaa\ddd   │   ├\xxx1\   │   └\yyy2\   │   ├\bbb\ddd   │   └\xxx3\   │   │   └\ccc\ddd       ├\xxx4\       ├\xxx5\       └\zzz6\ 1 C:\test1を指定する 2 1で指定した中にある各\dddフォルダ内にあるフォルダ名を順に取得する 3 2で取得したフォルダ名をExcelのSheet1のA1から順に書き出す Excel   A    B    C    D    E 1 xxx1 2 yyy2 3 xxx3 4 xxx4 5 xxx5 6 zzz6 7 8 9  Sheet1 Sheet2 Sheet3 勉強不足で申し訳ありません。 どうぞ宜しくお願い致します。

  • PerlでCSV形式のファイルの一部分だけを抽出する方法

    Perlをやっていて困っていることがあります。 CSV形式のファイルを開いて、変数に代入した後の処理がわかりません。 どのようにしたいかというと・・・ aaa,bbb,ccc,ddd,eee,fff ggg,hhh,iii,jjj,kkk,lll mmm,nnn,ooo,ppp,qqq,rrr sss,ttt,uuu,vvv,www,xxx yyy,zzz,111,222,333,444 というファイルを読み込んだとします。その後 'fff' の部分だけをスカラー変数に取り込みたいときにはどのような 関数を実行すればいいのでしょうか。 困っています、お願いします。

    • ベストアンサー
    • Perl
  • 【Microsoft Excel】 .csv 以外のCSVファイルをExcelで開きたい!

    .csv 以外のCSVファイルをExcelで開きたいのですがどうしたらよいでしょうか? abcd.csvというExcelで問題なく開けるCSVファイルがあるとします。 これの拡張子を.xxx(又はその他、独自設定の拡張子)に変更して、Excelで開けるようにしようと思ったのです。 フォルダオプション>ファイルタイプ>新規(ボタン)」で「新しい拡張子の作成」ダイアログが開き、そこで ・ファイルの拡張子=.xxx ・関連付けられているファイル タイプ=Microsoft Excel CSV ファイル と設定して、abcd.xxxをダブルクリックでExcelが起動&ファイルオープンするまではいったのです。(アイコンも.csvファイルといっしょになりました。) しかし、 aaa,bbb ccc,ddd という内容のファイルが セルA1=aaa,bbb セルA2=ccc,ddd となり、csvファイルとして認識してくれていないみたいなのです。 ちなみに、元の.csvの場合にはちゃんと セルA1=aaa セルB1=bbb セルA2=ccc セルB2=ddd とExcelは表示してくれます。 どうにか上手い方法は無いものでしょうか! よろしくお願いいたします。

  • 商品の売れ行きを一目で見るために・・・

    こんばんは。 商品の月別、店舗別の売上数を月、店舗コード、JANコード、を入力すれば一発で出るようにできるフォーマットを作りたいと考えています。 A   B C D E F G 1  月 店舗コード 店名 JAN 商品名 売数  2 0701 1  A 1111 vvv 200 3 0701 2 B 2222 xxx 200 4 0701 3 C 1111 vvv 600 5 0701 1 A 1111 vvv 10 6 0702 1 A 4444 yyy 800 7 0703 1 A 5555 zzz 1000 8 0703 3 C 2222 xxx 900 9 0704 1 A 1111 vvv 500 10 0704 2 B 2222 xxx 200 11 0704 3 C 2222 xxx 300 12 13 月 店舗コード 店名 JAN 商品名  売数  14 1~11までが今持っているデータベースとします。 店名と商品名はどこか別のデータからLOOKUPで引っ張ってくるとして、 B14とD14の二つを入力すれば、G14に数量が出るようにするにはどうすればよいでしょうか? どなたか知恵を貸していただけないでしょうか?

  • ファイル分割2

    前回ファイル分割について質問させていただいた者です。 ファイル名 あいうえお.txt 内容 <A>AAA <B>BBB <C>CCC <D>DDD <E>EEE <F>FFF というファイルを ファイル名 あいうえお1.csv A,B AAA,BBB ファイル名 あいうえお2.csv C,D CCC,DDD ファイル名 あいうえお3.csv E,F EEE,FFF という感じで変換させたいと思っております。 A,B,C,D,E,F AAA,BBB,CCC,DDD,EEE,FFF に変換するプログラムは my $mae = my $filename = shift @ARGV; my $ato = "$filename.csv"; open(IN,"$mae") || die "Can't open!"; my @datas = <IN>; close (IN); my (@ichi,@ni); foreach (@datas){ if ($_ =~ /^<(.*)>(.*)$/){ push(@ichi,$1); push(@ni,$2); } } my $ichi = join(",",@ichi); my $ni = join(",",@ni); open (IN,">$ato") || die "Can't open!"; eval 'flock(IN,2);'; seek (IN,0,0); print IN ("$ichi\n"); print IN ("$ni\n"); eval 'flock(IN,8);'; close (IN); exit; こんな感じで作成したのですが、前回教えていただいた3つファイルに分割するプログラムをどのように追加するか わかりません。 ほんとにあほみたいなことを聞いているとは思いますが、 教えていただけないでしょうか? よろしくお願いします。

    • ベストアンサー
    • Perl
  • SQL文 テーブル1つに複数のデータ

    お世話になっております。 SQLでの質問です。 --テーブル---------- F_1 F_2 AAA BBB AAA CCC BBB XXX CCC DDD DDD YYY 1.F_1のAAAを条件にF_2のBBB・CCCを取得し、 F_1のBBB・CCCと、F_2のXXXとDDDを取得します。 2.次に、取得したF_2のXXX・DDDを条件に、F_1のDDD、F_2のYYYを取得します。 これを1つのSQLで実行したいのですが、副問合せを駆使しても、良いSQLが思い浮かびません。 有識者の方、ご享受頂きたいです。 宜しくお願い致します。

専門家に質問してみよう