テキストファイル内の「誤改行」を修正する方法とは?

このQ&Aのポイント
  • perlを使用してテキストファイル内の「誤改行」を修正する方法について教えてください。
  • テキストファイル内の行の中には「誤改行」されて正常な行が分割されていて、これを修正したいと思っています。
  • 修文作業は途中まで成功していますが、最後の不要な行の削除ができない状況です。どうすれば解決できるでしょうか?
回答を見る
  • ベストアンサー

テキストファイル内の「誤改行」を修文したい!

perl は初心者です。よろしくお願いします。 ★無名ハッシュを作り、リファレンスをハッシュに格納する方法を採用して、試行錯誤しています。 ファイル内容は、論理行の一行毎に行頭が ”AA” のように””で囲まれています。(例文後述) しかし、行の中には「誤改行」されて正常な行が分割されていて、改行され行頭が””で囲まれていない行が存在します。(正常な行が2分割され、前半部分と後半部分が別な行文となっている) この「誤改行」を、直前にある「元の正常な分割された前半の行文」と連結して、新たな正常な行としてファイルを修正し新規テキストファイルに書きこみたい。この際、分割されていた2個の「行文」は不要になったので、新規テキストファイルには書き込まない。 この修文作業が、途中まで出来ましたが最後の不要な行の削除が出来ないので、困っています。 ------------------------------------------------------------ 対象とするテキスト内容 (下記の行番号と文字列は例示です) 1. "ABCD",あいうえおかきくけこ123456789 XXXXXXXXXXXX 2. "EFGH", 3. さしすせそたちつてと9876543 XXXXXXXXXXXX # ←「誤改行」の行です。 4. "IGKL",なにぬねのはひふへほ123456789 XXXXXXXXXXX 5. "MNOP",まみむめもやいゆえよ987654321 XXXXXXXXXXX 6. "QRST", 7. らりるれろわいうえを123456789 XXXXXXXXX # ←「誤改行」の行です。 8. 9. ------------------------------------------------------------------ 期待する修文の出力結果 (行内容は、元の行番号の順番と違っても結構です) 1. "ABCD",あいうえおかきくけこ123456789 XXXXXXXXXXXX 2. "EFGH",さしすせそたちつてと9876543 XXXXXXXXXXXX 3. "IGKL",なにぬねのはひふへほ123456789 XXXXXXXXXXX 4. "MNOP",まみむめもやいゆえよ987654321 XXXXXXXXXXX 5. "QRST",らりるれろわいうえを123456789 XXXXXXXXX 6. 7. ----------------------------------------- 私作成したスクリプトの要約は、 # 対象ファイルを一行づつ読み込む. # 末尾の改行を削除 # 誤改行の場合を正規表現で探す。$ng_gyou に格納 # その他正常行は$ok_gyou, に格納する。 # $falag に誤改行の場合は0、正常な改行の場合は1を格納 # 誤改行の場合の行番号を$count_ng に、正常な改行の場合の行番号を$count_ok に、全部の行番号は$flag_1に格納する。 # 無名ハッシュを作り,リファレンスを $ref に格納する $ref = {'nomber' => $flag_1, 'ng' => $ng_gyou, 'ok' => $ok_gyou, 'ngcount' => $count_ng, 'okcount' => $count_ok, 'flag' => $flag_ok }; $WORD{$flag_1} = $ref; # nomber:$flag_1をキーにして,リファレンスをハッシュ:%WORDに格納 # このハッシュ「%WORDを」 読み込んで、処理しました。 foreach $flag_1 ( sort { $a <=> $b } keys %WORD) {    if($one->{ok} == 0) { ・・・・・・・・・・・・・・・・・ # 細部は、長くなるので省略します。( 誤改行の連結までは成功しましたが、・・・・・・??) 以上、質問内容が冗長になりましたが、どうか御教示下さい。

  • Perl
  • 回答数8
  • ありがとう数8

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

  • ベストアンサー
  • osamuy
  • ベストアンサー率42% (1231/2878)
回答No.4

こことか: 「値に改行コードを含む CSV形式を扱う」 http://www.din.or.jp/~ohzaki/perl.htm#CSVwithCRLF 改行を含んだCSVデータの読み方の話だとしたらですが。 (サンプル7行目「安全高度爆発(safe height burst)」にダブルクォートがついてないのは、typoと予想)。 そうでなく、「先頭が"始まりでなければ前行に追加」というだけなら、こんなのとか: my $cr = ''; while (<> ){ print $cr if /^"/; $cr = chomp == 0 ? '' : $/; print; } print $cr;

参考URL:
http://www.ideone.com/IPF7C
daiden-ina
質問者

お礼

御教示を有難うございました。私が実際に扱う対象の「例示したデーター」では成功しました。 chompの使い方が勉強不足でよくわかりませんが、便利な方法があるのですね! ------------------------------------------------------ < 「先頭が"始まりでなければ前行に追加」というだけなら、 そのとうりですが、今回のコードを使って前回の例示デターを処理すると、上手くできませんでした。「誤改行」の形が千差万別の感があり規則性はありませんので、如何なる形でも処理できる汎用性のあるコードが、私の願望でありますので宜しく御教示の程お願いします。 < サンプル7行目・・・・ これは、「誤改行」の行で、前行に続く文字列です。 ------------------------------------------------------ <「値に改行コードを含む CSV形式を扱う」・・・・・・・・ ご指摘のとうりで、CSV形式の処理方法です。ご教示のWebサイトを見ながら勉強してみます。 対象デターは、約4万行~3万行の数個のcsv形式ファイルです。エデターで正規表現検索で手作業で修正していましたが、月に一度はデターを点検するのでperlを使った処理を勉強中です。千差万別の感がある「誤改行」を、私が手作業で検索(正規表現)する際には、次のように検索したら、概ね全ての「誤改行」をヒットするようでしたので、ご参考になれば幸いです。 /^¥s+|^¥n|^"¥n|^[^"]|^"¥s / 以上、お礼とともに更なるお願いをいたしました。

その他の回答 (7)

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

>「あらゆるケースに対応したコードを書くのは大変」なので、コード作成は諦めた方が良いのでしょうか! あらゆるケースに対応することをあきらめれば簡単に書けます。 「行頭が " で始まらない行があれば、前の行に続ける」 だけであれば、私がNo2に書いた sed スクリプトでも良いし、Perlなら、 $x=""; while(<>){ chomp($x) if /^[^"]/; print $x; $x=$_; } print "\n"; 末尾の空行も消えちゃいますが。

daiden-ina
質問者

お礼

御教示を有難うございました。 osamuyさんのANo.4の御教示と同様に「例示のDATA」で成功しました。 ----------------------------------------------------------- < あらゆるケースに対応することをあきらめれば簡単に書けます。  「行頭が " で始まらない行があれば、前の行に続ける」 ----------------------------------------------------------- ★ あらゆるケースに対応することを諦めます! ベストアンサーには、先に御教授頂いたosamuyさんのANo.4を選ばせて頂きました。   どうか御寛容の程、お願いします。 付記;  chomp の使い方を、これから詳しく調べますが全く勉強不足でした。私には、御教授のコードの意味が理解できません。  while(<>)文で、DATA一行毎に読む込んだ場合において、既に読み込んだ行の前行に遡って前行のDATA内容を処理できるとは、想像できませんでしたので、全部の行を読み込み変数に格納してから、これを取り出して処理する方法を考えていました。  従って、多重のデータ構造を無名ハッシュのリファレンスで構築しました。検索した「誤改行」の行番号と内容を変数に格納し、直前の行番号と内容を連結させる処理を考えました。行番号をキーにした無名ハッシュのリファレンスを、デリファレンスしながら読み込んだデータを処理すれば、汎用性あるコードになると思案した次第です。

回答No.7

例だけを見ていると 行の末にカンマがある場合が誤改行とすれば、 一行読み込み、最後がカンマではなければ、書き出す カンマであれば、次の行を読んで合わせて、書き出す というのはどうでしょうか。 一行が複数に誤改行があるようでしたら、 行末がカンマでない行を読むまで、読み込んだものを累積して書き出す というような事でもよいかと思いますが。

daiden-ina
質問者

お礼

御教示、有難うございます! 私の例示データの説明不足のようです。 例示のデータは「DATAファイル」を、テキストエデターで読み込んで表示される画面を、正確に記述したつもりでした。  エデターの設定が「行番号・論理行を表示する」とした場合、表示される内容です。 従って、例示の行番号は「DATAファイル」の内容には含まれておらず、行番号が違う行は改行されているのです。 本来は論理行の「一行で表示されるべき行」が分割されている行があるので、「誤改行」と呼称しました。これを直前の行の末尾に連結する方法を求めております。 ----------------------------------------- < 例だけを見ていると・・・・ < 行の末にカンマがある場合が誤改行とすれば、 ★ 行末のカンマは関係ありません、誤改行ではありません。   6."Types of burst","爆発形態・・・ の行をご覧下さい。   次行の 7.水中核爆発・・・という行は、6."Types of burst"の続きの説明です。   「誤改行」された内容が、7.水中核爆発・・・ の行です。 ------------------------------------------- 以上、「例示したDATA」の説明を補足しました。

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

NO1のお礼を見る限り、「誤改行」というよりは、「データに改行が含まれたCSV」ですね。 CSVは、" " で囲んだ中に改行を入れても良いのです。誤りではありません。 CSVを扱うには、自分であらゆるケースに対応したコードを書くのは大変なので、ライブラリを使うと良いでしょう。 http://search.cpan.org/search?query=CSV&mode=all

daiden-ina
質問者

お礼

notnotさん! 御教示を有難うございました。  「あらゆるケースに対応したコードを書くのは大変」なので、コード作成は諦めた方が良いのでしょうか! ------------------------------------------------------------ < CSVを扱うには、自分であらゆるケースに対応したコードを書くのは大変なので、ライブラリを使うと良いでしょう。 http://search.cpan.org/search?query=CSV&mode=all ------------------------------------------------------------ ご紹介の方法を、これから勉強してみます。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.5

#1 のお礼に書いてある例文で, 「期待する結果」なるものがどのような処理の結果なのか「正確に」書いてみてください.

daiden-ina
質問者

お礼

Tacosan さん! ご指摘を有難うございます。私の文章が拙くて申し訳ありませんでした。 #1 のお礼に書いてある例文の最後の段落に、「期待する修文した出力」として書いておきましたが、説明不足で申し訳ありませんでした。  元のデーターの行番号の1~8行が、「期待する修文した出力」においては1~6行になることを期待しています。 元データーの「誤改行」は、行番号の3行目と7行目です。この行を、直前の行の末尾に連結させるので、合計2行が減ります。

  • shiren2
  • ベストアンサー率47% (139/295)
回答No.3

そのまま書いてみました。 動作確認済みです。 #!/usr/bin/perl use strict; my @list; while(<DATA>){ #行末の改行を除去 chomp; #行頭の数字を除去 s/^\d+\. *//; #配列に入れておく push @list, $_; } for(my $i=0; $i<@list; $i++){ #行頭の数字は1から始まる printf("%d. %s", $i+1, $list[$i]); #異常な行ならば次の行を取り出して繋げる if($list[$i] =~ /,$/){ printf("%s", splice(@list, $i+1, 1)); } #改行を出力 printf("\n"); } __DATA__ 1. "ABCD",あいうえおかきくけこ123456789 XXXXXXXXXXXX 2. "EFGH", 3. さしすせそたちつてと9876543 XXXXXXXXXXXX 4. "IGKL",なにぬねのはひふへほ123456789 XXXXXXXXXXX 5. "MNOP",まみむめもやいゆえよ987654321 XXXXXXXXXXX 6. "QRST", 7. らりるれろわいうえを123456789 XXXXXXXXX 8. 9.

daiden-ina
質問者

お礼

懇切な御教示を頂き、有難うございました。 私の質問内容が拙劣で、ご迷惑をかけます。実は行番号はエデターで表示した際の番号であり、ファイル内容には含まれておりません。 このため、行番号を変数に格納して、処理する必要があったのです。 どうも、舌足らずの質問で、誠に申し訳ありませんでした。(osamuyさんのお礼の中で、質問文を補足しました。)

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

この程度はsedで出来そうなのでやってみました。 下記の内容をファイル x に書いて、sed -n -f x 入力ファイル > 出力ファイル で。 1{ h d } /^[^"]/{ H x s/\ // x d } x p ${ x p }

daiden-ina
質問者

お礼

早速の御教示を有難うございました。 sedは以前に使いましたが、細部は手馴れていないので後ほど試してみます。

  • osamuy
  • ベストアンサー率42% (1231/2878)
回答No.1

こんな感じ? while ( <> ){ chomp if /^".+?",$/; print; }

参考URL:
http://www.ideone.com/ZsrbL
daiden-ina
質問者

お礼

御教示を有難うございました。 私が例示したファイルでは、お蔭さまで修文が出来ました。 なお、申し訳ありませんが、私の例示したファイル内容文が、適切ではありませんでした。 ----------------------------------------------------------------------------- ★実は、次のようなファイルの内容を修文した場合、期待した修文はできませんでした。 (行番号の3行目と、7行目が誤改行です) 1."ACP","aviator continuation pay <空>","" 2."BDS-D","Battlefield Distributed Simulation-Developmental 戦場分散状況シミュレーション; ATD段階<陸><M&S> cf. DIS 3.http://www.fas.org/man/dod-101/army/docs/astmp/c6/P6C3.htm","" 4."LZCO","landing zone control officer 降着(着陸/揚陸)地域統制将校(Mil.Terms)","" 5."M","mega メガ; 10(6)、 10の6乗、 百万、 million<SI>","" 6."Types of burst","爆発形態; 空中爆発(airburst)、 フォールアウト回避高度爆発(fallout safe height of burst)、 高空爆発(high airburst)、 高高度爆発(high altitude burst)、 低空爆発(low airburst)、 空中核爆発(nuclear airburst)、 大気圏外核j爆発(nuclear exoatmospheric burst)、 地表接触核爆発(nuclear contact-surface burst)、 地表近接核爆発(nuclear proximity-surface burst)、 地下核爆発(nuclear underground burst)、 7.水中核爆発(nuclear underwater burst)、 最適高度爆発(optimum height burst)、 安全高度爆発(safe height burst) ,"" 8."V","Volt ボルト; 電圧/起電力のSI組立単位<SI> ","" 9. -------------------------------------------------- 期待する修文した出力 1."ACP","aviator continuation pay 航空<空>","" 2."BDS-D","Battlefield Distributed Simulation-Developmental 戦場分散状況シミュレーション; ATD段階<陸><M&S> cf. DIS http://www.fas.org/man/dod-101/army/docs/astmp/c6/P6C3.htm","" 3."LZCO","landing zone control officer 降着(着陸/揚陸)地域統制将校(Mil.Terms)","" 4."M","mega メガ; 10(6)、 10の6乗、 百万、 million<SI>","" 5."Types of burst","爆発形態; 空中爆発(airburst)、 フォールアウト回避高度爆発(fallout safe height of burst)、 高空爆発(high airburst)、 高高度爆発(high altitude burst)、 低空爆発(low airburst)、 空中核爆発(nuclear airburst)、 大気圏外核j爆発(nuclear exoatmospheric burst)、 地表接触核爆発(nuclear contact-surface burst)、 地表近接核爆発(nuclear proximity-surface burst)、 地下核爆発(nuclear underground burst)、 水中核爆発(nuclear underwater burst)、 最適高度爆発(optimum height burst)、 安全高度爆発(safe height burst) ,"" 6."V","Volt ボルト; 電圧/起電力のSI組立単位<SI> ","" 7. -------------------------------------------------------- ▼注記:  "XXX" で囲った範囲が、一行の中に数個含まれています。 以上、全便の質問内容を変更して申し訳ありませんでした。

関連するQ&A

  • C言語を使って、ファイルの読み込みをして切り出して2次元配列に格納した

    C言語を使って、ファイルの読み込みをして切り出して2次元配列に格納したいのです。 1,2行目に配列の行の数と列の数が書かれ、3行目から改行とカンマ、スペースで区切られて配列が書かれているテキストを読み込んで2次元配列に格納する。 テキストの例) 4 3 1.1 1.2 1.3 1.4 1.5 2.1 2.2 2.3 2.4 2.5 3.1 3.2 3.3 4.4 3.5 というプログラムを書いています。色々と参考書やサイトを参考してとりあえずの形にはなったと思ったのですが、実行してもエラーが出ます。 どこまで動いているか調べたところ、一行ごとに読み出してそれを切り出して行くところでおかしな事をしてしまっているようですが、どう変えたらいいものか分かりません。 なので、その点のアドバイスと 大きさの分からないファイルから1,2行目を読み出すのはこれで変な動きをする恐れはないか の2点についてヒントでも構わないので、教えてください。 以下、書いたソースです(申し訳ないのですが、文字数の関係で一部省略しています。) #include <stdio.h> #include <stdlib.h> #include <string.h> int main(int argc, char *argv[] ) { double ** mainhairetu; int size_x, size_y; /* size_x 行 size_y 列 */ int i,j,count=0,count2; int *cut,*temp2; double temp; char s2[] = " ,"; char gyou[10],*num; FILE *fil; while((fgets(gyou,10,fil)) !=NULL){ if(count == 0){ size_x=atoi(gyou); count++; }else if(count ==1){ size_y=atoi(gyou); count=count+1; }else{ break; } } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ここでmallocを使ってcutとmainhairetuの2つの配列を作っています。 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ count=0; for (i = 0; i < size_y+2; i++) { mainhairetu[i][0] = atof( strtok( fgets(cut,50,fil),s2 ) ); for (j = 1; j < size_x; j++){ if(count <=1){ count++; break; }else{ mainhairetu[i][j] = atof( strtok( NULL,s2 ) ); } } } for(i=0;i<size_y;i++){ for(j=0;j<size_y;j++){ printf("%f",mainhairetu[i][j]); } printf("\n"); } return(0); }

  • スカラー変数中の改行コードでセパレーションしたい。

    複数行に渡る文字列を含むデータをスカラー変数に格納したのですが 格納後にこれを改行コード(\n)をセパレータとして配列に分けたいと思っています。 データ(abc.txtd)は aaaaaa bbbbbb cccccc といったものです。 $data = "abc.txt"; @array = split (/\n/, $data); としてもうまく配列に分割してもらえないのですが、どうすればよいのでしょうか。 基本的な質問で申し訳ありませんが、どなたかよろしくお願いいたします。

    • ベストアンサー
    • Perl
  • VBA SUM関数に変数を入れた計算式の書き方

    図のような表があります。 この表で、B1~B2、B6~B7は1行から4行の間で変化します。 ただし、B1~B2の行数とB6~B7の行数は同じです。 A10のセルに=SUM(B6,B7,(B6-C6*B2/100),(B7-C7*B3/100))という計算式を入れたいのですが 上記のように行数が変化するので B1=cells(gyou,2) B2=cells(gyou1,2) B6=cells(gyou+5,2) B7=cells(gyou1+5,2) c6=cells(gyou+5,3) c7=cells(gyou1+5,3) としています。ここでgyou1は1から4の間で変化します。 ほんとうは cells(gyou+9,1).Formula=SUM(cells(gyou+5,2):(cells(gyou1+6,2)-cells(gyou1+6)*cells(gyou1,2)/100)) とできると良いのですが、エラーになります。 SUM(cells(gyou+5,2):cells(gyou1+5,2))はOKですが、 SUM((cells(gyou+5,3)-cells(gyou+5,2)*cells(gyou,2)/100)):(cells(gyou1+5,2)-cells(gyou1+5,3) _   *cells(gyou1,2)/100))が、NGです。 これをどのようにコードを書くと良いのか教えて下さい。

  • マクロ VBA 配列内の比較方法

    いつも大変御世話になっております。 WiindowsXP環境にある【D:\】フォルダ内に【マクロ.xls】があります。 そのファイル内にはボタンがあり、 ボタンを押すとマクロが稼働します。 そのプログラムには数字を格納する配列 FLAG(1 to 10) があり 毎回ボタン押すごとに入る数字が違います。 入る数字は 1 と 0 しか入らない仕組みです。 例) 1001101101 や 0110100110 のように毎回違います。 問題はその後のプログラムなのですが 都合上、 (1)3桁目と5桁目が1の場合 (2)4桁目と6桁目が1の場合 (3)4桁目と7桁目が1の場合 (4)7桁目と8桁目が1の場合 であってはいけないので それをチェックするプログラムを作成したのですが、 下記のような長ったらしい文になりました。 ---------------------------コード開始--------------------------- (省略) If FLAG(3) = 1 And FLAG(5) = 1 Then GoTo NG: ElseIf FLAG(4) = 1 And FLAG(6) = 1 Then GoTo NG: ElseIf FLAG(4) = 1 And FLAG(7) = 1 Then GoTo NG: ElseIf FLAG(7) = 1 And FLAG(8) = 1 Then GoTo NG: Else GoTo OK: End If NG: MsgBox "NG" Exit Sub OK: MsgBox "OK" (省略) ---------------------------コード終了--------------------------- もっと綺麗なコード設計は可能でしょうか? もしご存知の方がいらっしゃるようでしたら、お手数ですがご教授願いますでしょうか? 以上、何卒宜しくお願い致します。

  • ハッシュのリファレンスを用いた処理

    ActivePerl 5.8 , WinXP SP2の環境です。 Perl スクリプトを用い、ファイルから複数のブロックからなる情報をよみとり、個別のハッシュを作り、それをリファレンスの配列としてまとめて後から参照するという操作をしたいのですが、詰まってしまいました。。 例として読み取るファイルは ---input.txt--------- >1 Jan 1 Feb 4 >2 Mar 9 Apr 3 >3 Oct 8 Nov 4 ------------------ ここから1,2,3の個別のハッシュ {Jan => 1 Feb => 4} {Mar=> 9 Apr =>3} {Oct =>8 Nov =>4} を作成し、それぞれのハッシュのリファレンスの配列をつくり、その後からすべてのハッシュの中身を個別に出力させたいと思いました。 次のようなスクリプトを作成したのですが思ったように作動しません。 use strict; open (IN, "input.txt") or die ("cant open file \n"); my $reff; my @array_of_reff; my %hash; my $count = 0; while(<IN>){ my $line = $_; ######ここでは各ブロックの頭の ">"を認識し、2個目以降であれば直前までで作ったハッシュのリファレンス($reff)を配列@array_of_reffに入れる。 if($line =~ /^>/){ if($count >0){ $reff = \%hash ; push (@array_of_reff, $reff); %hash = (); } $count++; } ########ここではアルファベットが入った行を認識して、ハッシュに追加しています if($line =~ /^[A-Za-z]/){           $line =~ /([A-Za-z]+)\s+/; my $month = $1; $line =~ /\s+(\d+)/; my $day= $1; $hash{$month} = $day;     } ###ここはファイルの最後になったら直前まで作っていたハッシュののリファレンス($reff)を配列@array_of_reffに入れる。 if( eof ){ $reff = \%hash ; push (@array_of_reff, $reff); } } #####ハッシュのリファレンスの配列(@array_of_reff)からもとのハッシュを参照し、ハッシュごとに出力 foreach my $reff_of_hash (@array_of_reff){    print "output";    while( (my $key,my $value) = each %$reff_of_hash ){     print "\n" , $key, " : ", $value, ;    } } このスクリプトを実行すると Nov 4 Oct 8 という3つめのハッシュのなかみが3回出力されてしまいます。自分では3つの別のハッシュをつくっているつもりでも、どうやら1種類しか作れていない、もしくはハッシュが上書きされているようなのですが、原因がわかりません。 この例だけ見るとハッシュのリファレンスを使う必要はないのですが、実際にはもうすこし大きいスクリプトで"ハッシュのリファレンスの配列を他のサブルーチンに渡す"ということを想定しており、これが解決できず先に進めない状態です。 アドバイス、解決法がわかったら教えていただけないでしょうか。

    • ベストアンサー
    • Perl
  • DBMとテキストファイルのどちらが良いと思われますか?

    こんにちは、 windows + ActivePerl の環境で、 簡単なデータを記録して後から検索、修正、削除したいのですが、 データを格納するのに、テキストファイルにするか、DBMを使用するか 悩んでいます。 テキストファイルに、(行番号,"*" x 100)のレコードを10万行出力したら、約10MBで、 DBMファイルに (行番号=>"*" x 100)のハッシュを出力したpagファイルは510MBでした。 その後、99999番目のレコードを以下のスクリプトで表示したところ、 体感的には違いがありませんでした。(どちらも一瞬で終了します) ******************************* #テキストファイル 検索 my $id = 99999; my $data; open(FILE,"<TEXTfile.txt") or die ; while(my $line = <FILE>){ if($line =~ /$id/){ $data = $line; last; } close FILE; print $data; ******************************* #DBMファイル 検索 my %DBM = (); my $id = 99999; my $data; dbmopen(%DBM,"DBMfile",0666) or die; if (defined $DBM{$id}){ $data = $DBM{$id}; } dbmclose %DBM; print $data; DBMを使用した場合、すべてのデータをメモリ上に展開するのでしょうか? もしそうなら、510MBも消費されてはたまりませんので、テキストファイルになりますが、 コーディング等はDBMの方が楽かな?と考えています。 データベースを利用できない環境の場合、どちらが良いのでしょうか? ご意見お願いします。

    • ベストアンサー
    • Perl
  • 値によって組み分けを作成するプログラムについて

    こんにちは。 プログラミングでつまってしまったため質問させて頂きます。 プログラミング言語はC++です(visual c++ではありません)。 ■作成したいプログラム A,B,C,D,Eがある。 AとBの類似度は91% 以下同様に AとCは89% AとDは79% AとEは77% BとCは93% BとDは97% ・・・のように続いていく.. (*ABが似ている、BCが似ている。だからと言ってACが似ているとは言えない。) この中で、類似度が閾値以上である場合は同じ組とする。 ただし、複数のパターンが考えられる場合は組の数が一番すくなくなるように作る。 ■プログラムの動作イメージ 例1: 閾値=0.90 //入力データ 01 = 0.91; OK 02 = 0.90; OK 03 = 0.78; NG 04 = 0.83; NG 12 = 0.94; OK 13 = 0.78; NG 14 = 0.77; NG 23 = 0.78; NG 24 = 0.69; NG 34 = 0.94; OK OKなのは,01,02,12,34 つまり以下のような出力が得られる >>0,1,2 >>3,4 --------------------------------------- 例2: 閾値=0.90 //入力データ 01 = 0.91; OK 02 = 0.90; OK 03 = 0.94; OK 04 = 0.83; NG 12 = 0.95; OK 13 = 0.78; NG 14 = 0.77; NG 23 = 0.78; NG 24 = 0.69; NG 34 = 0.94; OK OKなのは,01,02,03,12,34 つまり 0,1,2 3,4 or 0,3 1,2 4 となった場合は、組数の少ない上を選択する。 従って以下のような出力が得られる。 >>0,1,2 >>3,4 --------------------------------------- 例3: 閾値=0.90 //入力データ 01 = 0.91; OK 02 = 0.90; OK 03 = 0.78; NG 04 = 0.83; NG 12 = 0.77; NG 13 = 0.78; NG 14 = 0.77; NG 23 = 0.78; NG 24 = 0.69; NG 34 = 0.94; OK OKなのは,01,02,34 この場合は、01と02は閾値を超えているが、12は閾値を超えていないため、 0,1,2を同じ組とはできない。 従って以下の2パターンが考えられる。 0,1 2 3,4 or 0,2 1 3,4 この場合は組の数は同じなのでどちらが出力されてもOK。 番号の若いものから出力されるとすると以下のような出力が得られる。 >>0,1 >>2 >>3,4 ------------------------------------------------------ 以上のようなプログラムを作成したいです。 自分で考えてみたのプログラムが以下のものです。 01,02,12,34は閾値を超えているということまではできたのですが、その後のグループの作り方のところで詰まってしまいました。 そこで、上記のような動作をするプログラムについて教えていただきたいです。 よろしくお願い致します。 int main(){ //閾値 double THRESHOLD = 0.9; //dataを格納する配列 double in_data[5][5] = {0}; //group_flagを格納する配列 bool group_flag[5][5] = {0}; in_data[0][1] = 0.91; in_data[0][2] = 0.90; in_data[0][3] = 0.78; in_data[0][4] = 0.83; in_data[1][2] = 0.94; in_data[1][3] = 0.78; in_data[1][4] = 0.77; in_data[2][3] = 0.78; in_data[2][4] = 0.69; in_data[3][4] = 0.94; //組の番号を格納する配列    //group[3]=2だったら、データ3はグループ2に入る int group[5]; int i=5; //データ数 int num=0; for(int n=0; n<=i; n++){ for(int m=n+1; m<i ;m++){ cout << "in_data[" << n << "][" << m << "]=" << in_data[n][m] << endl; if(in_data[n][m] >= THRESHOLD){ cout << "OK" << endl; group_flag[n][m] = 1; } } } for(int n=0; n<=i; n++){ for(int m=n+1; m<i ;m++){ if(group_flag[n][m] == 1){ cout << n << m <<endl; } } } }

  • ファイル出力時の

    以下のソースでファイル出力するのですが、 BufferedReader br = new BufferedReader(new FileReader(new File(args[0]))); PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(args[1]))); //一行読み込みを行った文字列を格納 String line; //一行読み込み while((line = br.readLine()) != null){ //一行書き込み pw.write(line); System.out.println(line); } コンソールへの出力は正常に出力されるのですが、 ファイルへの出力は改行されずに一行で出力されてしまいます。 どうすればファイル出力も正常になるか教えてください。

  • PHPからデーターの渡し方で悩んでます

    PHP初心者です。 質問の仕方がおかしいかもしれませんが教えてください。 ウィンドウズ上で動くソフトがあります。 そのソフトで、IDとパスワードを入力してPOST送信 PHP側でデーターを受け取る。 IDとパスワードが認証されたなら ソフトに”OK”という文字列を返す。 認証されなかったら ”NG”を返すPHPを作成してほしいと頼まれました。 ”OK” ”NG"をどのようにソフトに渡したらよいかがわかりません。 一応このような感じでPHPを作成しているのですが $u_id = $_POST['u_id']; $passwd = $_POST['passwd']; $pa_data = file($data_file); $pa_flag = 0; for($i=0; $i<count($pa_data); $i++){ list($id,$pass) = split(",", $pa_data[$i]); if($id == $u_id && $pass == $passwd){ $p_flag++; } } if($pa_flag > 0){ *****"OK文字列を返す"; } else { *****"NG文字列を返す"; } ウィンドウズ上で動くソフトが何でつくられたかがわからないので答えにくいかもしれませんが *****"OK文字列を返す" *****"NG文字列を返す" の部分を具体的に教えていただきたいと思います。 よろしくお願いいたします。

    • ベストアンサー
    • PHP
  • ハッシュ(単語数を数える) たのしいRuby

    たのしいRuby P252に掲載されていた、例題 「ハッシュ(単語数を数える)」の解説を読んでも 意味が分からなかったので教えてください。 ■例題word_count.rb 1:# 単語数のカウント 2: 3: count = Hash.new(0) 4: 5:## 単語の集計 6:while line = gets 7: words = line.split 8: words.each{|word| 9: count[word] += 1 10: } 11:end 12: 13:## 結果の出力 14:count.sort{|a,b| 15: a[1] <=> b[1] 16:}.each{|key, value| 17: print "#{key}: #{value}\n" 18} ■疑問1. 解説には、 # 3行目で出現回数を記録するハッシュcountを作ります。 # countは、キーが単語、値がその単語が出現した回数を表します。 と書かれているのですが、「キーが単語、値がその単語が出現した回数を表します」 の内容が理解できません。newしただけなのに、どうして、 キーと値の内容が決まるのでしょうか? ■疑問2. 解説には、 # 8行目からの繰り返しでは、それぞれの単語をキーにして、countから出現回数を取り出し、 # +1します。 と書かれているのですが、「count[word] += 1」 の内容が理解できません。 作成したハッシュcountと、getsメソッドで読み込み単語単位に分割した配列wordsとが、 どこで関連付けされているのかが、分かりません。 ■疑問3. 解説には、 # ruby word_count.rb README という形で、Rubyに同梱されているREADMEファイルの単語数を調べた 実行結果が掲載されているのですが、 そのときの具体的な処理の流れが分かりません。 「ruby word_count.rb README」と書くだけで、 処理の流れが、getsの所まできたとき、 自動的に指定ファイル名を判断し、 読み込みを始めるということなのでしょうか。

    • ベストアンサー
    • Ruby

専門家に質問してみよう