Perlでカンマ区切りのデータから指定されたワードを抽出する方法

このQ&Aのポイント
  • Perlのプログラムで、カンマ区切りのデータから指定されたワードを抽出する方法を教えてください。
  • 特定のワードを含む行のみを抽出したい場合、`grep`関数を使用することができます。
  • 抽出した行から特定のワードのみを取り出す場合、正規表現を使用して抽出することができます。
回答を見る
  • ベストアンサー

perlで検索 カンマ n番目

~log.txt~ 1,a,w,e,r 2,a,w,e,r 2,e,a,v,ssss 3,s,ssss,a,a $FILE = 'log.txt'; $Search = 'sss'; ~Search.pl~ open(FILE, "<$FILE") or die("error :$!"); eval{ flock(FILE, 1) }; @DATA = <FILE>; close FILE; $a = 0; my @Search = grep(/$Search,/, @DATA); while (<@Search>) { $a++; } print "@Search\n"; このようなデータで 検索ワード=sssのとき ヒットするのが 2,e,a,v,ssss 3,s,ssss,a,a [0][1][2][3][4] この2つです。 ここまではいいのですが、 2番目のsssのみを取り出したいとき my @Search = grep(/$Search,/, @DATA); ここをどのように変えればいいのでしょうか・・・?

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

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

  • ベストアンサー
回答No.3

push @Search, [$field[2], $line] if $field[2] =~ /s/; とすると、配列 @Search は配列の配列になります。 [[2 番目のフィールド, 行全体], [2 番目のフィールド, 行全体], ...]

Cells231
質問者

お礼

ありがとうございました! 実行でき解決できました!

その他の回答 (2)

回答No.2

正規表現も良いですが、2番目のフィールドとわかっているのなら、 コンマで分割してからマッチすれば良いような。 foreach my $line (@DATA) { my @field = split /\s*,\s*/, $line; push @Search, $field[2] if $field[2] =~ /s/; }

Cells231
質問者

お礼

説明不足で申し訳ないです;;

Cells231
質問者

補足

説明不足でした。すみません・・・ ご掲示くださったソースで、しっかり「sを含む文字列」を探しだすことに成功しました。 ただ、フィールドの[0][1][3]もほしいのです・・;; ご掲示くださったソース での実行結果 1,a,w,e,r 2,a,w,e,r 2,e,asa,v,ssss 3,s,ssss,a,a ↓ asa ssss 結果的には 1,a,w,e,r 2,a,w,e,r 2,e,asa,v,ssss 3,s,ssss,a,a ↓ 2,e,asa,v,ssss 3,s,ssss,a,a (@Search)

回答No.1

/\A(?:[^,]+,){2}$Search/ はどうでしょうか。

Cells231
質問者

お礼

ありがとうございます。 最後に、もう1つご教示お願いいたします

Cells231
質問者

補足

ご回答ありがとうございます。 やりたいことはこれです! しかし、1文字目の文字だけでなく 文字列の中に含む場合、どうするのでしょうか・・・? 例) 検索ワード 「s」 ヒットワード 「moshi」

関連するQ&A

  • アスタリスクを文字列として変数に入れるには

    HP-UX cshで、アスタリスクを文字列として 変数に入れるにはどうしたら良いでしょうか? 現在は <file3の中身> grep -v file*.txt | grep -v file2.txt で、 set hensu=`cat file3.txt`としてecho $hensuすると grep -v file1.txt file2.txt file3.txt | grep -v file2.txt という具合に、アスタリスクがワイルドカードとして 働きます。これを「file*.txt」という文字列として 変数に入れる方法を教えてください。 宜しくお願いします。

  • Perl 処理速度について

    ブログを作成し、カテゴリー別に分けたく下記のようなソースを 書きました。 sub category1 { open(FILE, "<$FILE") or die("error :$!"); eval{ flock(FILE, 1) }; @DATA = <FILE>; close FILE; $a = 0; my @category1 = grep(/,1,/, @DATA); while (<@category1>) { $a++; } &buffer(); if($start > @DATA) {$start = @DATA;} $next = $start + 100; $back = $start - 100; if ($back < 0) { $back = 0; } for ($i=$start;$i<$next;$i++){ last if ($i > @category1); $data = $category1[$i]; &page(); } } これの処理速度が遅いのですが、なにか原因はありますでしょうか? 似たような処理で下記のソースの方が、読み込む内容としては多いのですが、 こちらは普通の速度です。 sub diary2017 { open(FILE, "<diary/diary-2017.txt") or die("error :$!"); eval{ flock(FILE, 1) }; @DATA = <FILE>; close FILE; &buffer(); if($start > @DATA) {$start = @DATA;} $next = $start + 1000; $back = $start - 1000; if ($back < 0) { $back = 0; } for ($i=$start;$i<$next;$i++){ last if ($i > @DATA); $data = $DATA[$i]; &page(); } } カテゴリーのサブルーチンとアーカイブ専用のサブルーチンで違う点といえば $a = 0; my @category1 = grep(/,1,/, @DATA); while (<@category1>) { $a++; } このgrepのとこですが、 これが遅いとすると対処方法はありますか? ※開くファイルはアーカイブは直接名前にしてて、カテゴリーは変数を使ってますが  これは同じです。

    • ベストアンサー
    • Perl
  • PHPで、○番目のカンマの文字を呼び出す方法

    0,123,45,678,999 など、カンマ区切りの情報がある data.txt というファイルがあり、 別のPHPファイルにdata.txtの内容を書き出したい場合、 <?php echo file_get_contents("data.txt"); ?> と書くと全部表示されてしまいます。 data.txtの1行目で、2番目と3番目のカンマの間の数字(上の例ですと123)を書き出すには、どのように書いたらよいか、お分かりになる方教えて頂けませんでしょうか。 よろしくお願いいたします。

    • ベストアンサー
    • PHP
  • ログファイルを後ろから検索し、最初のマッチで止める

    CentOS 5 を使っています。 とある巨大なログファイルがあります。 例えば grep hoge log.txt | tail -1 みたいな事をやっているのですが、これをどうにか高速にできないですかね? 上記だと、ログファイルを全検索しているので効率が悪いです。 (ログファイルはファイルの最後の方に新しい情報が記録されているので、その最新ログが見たいのです) 安易に思いつくのは tac コマンドを使って tac log.txt | grep hoge | head -1 でもいいんですが、grep で「最初のマッチで終了」してくれるオプションもなさそうです。 何か良い方法があればご教示願います。 (ruby 等でスクリプトを書いても良いのですが、何とかワンライナーで出来ないかなと) P.S ちなみに実際の見たい情報は「grep でマッチした前後数行」なので -A や -B オプションを使っています。

  • perlで文書を読み込み検索置換したい

    MAC OS Xを使用しています。 検索置換のプログラムをperで作成し、Applescript上で呼び出したいのです。 実際はファイルメーカーのスクリプトの中でApplescriptを記述してその中で呼び出したいのです。 do shell script "perl ~.pl"という感じで使えるのではないかと 下記のようなサンプルスクリプトを見つけたのですが 内容の更新の仕方がよく分かりません。 perlについては全くの初心者でいろいろ調べたのですがよく理解できませんでした。 検索置換したいのですが、どういうふうに書けばいいのでしょうか。 (2)の部分を教えて下さい。宜しくお願いします。 use strict; use warnings; use File::Copy 'move'; # (1) ファイルの内容を読み込む my $file = 'F:\共有\PERL\test.txt'; open my $fh, '<', $file or die qq/Can't open file "$file": $!/; my $content = do {local $/; <$fh>}; close $fh; # (2) 内容の更新 ▼をリターンに置き換えたいのです。 $line =~s/▼/\n/; # (3) 一時ファイルへの書き出し my $temp_file = "$file.$$." . int(rand 10000); open my $temp_fh, '>', $temp_file or die qq/Can't open file "$file": $!/; print $temp_fh $content; close $temp_fh or die qq/Can't open file "$file": $!/; # (4) 一時ファイル名を元のファイル名に変更 move $temp_file, $file or die qq/Can't move "$temp_file" to "$file": $!/;

  • perlで以下の動作が出来る機能を作っています。

    perlで以下の動作が出来る機能を作っています。 1.ファイル名が載っているfname.txtを読み込む。 2.読み込んだファイル名を開く。 3.ファイルの内容を変換。 4.変換したファイル内容をnew_fileディレクトリに保存。※ファイル名はそのまま。 1~4までを作ったのですが、fname.txtで指定した全てのファイル名を変換して保存したいのに、一番最初に記載されてあるファイル名しか置換されません。書籍などで調べてもわからないのと今日中に製作したいのでここで質問しました。 ご教授お願いします。 以下にソースを貼ります。 #!/usr/local/bin/perl -w use strict; my $x = 0; my $y = 0; my $z = 0; open(IN,"<"."fname.txt")or die "cannot open txt_file: $!";#fname.txtを開く while(<IN>){ #chomp $_;#改行してファイル名を書き込んでいるので、改行を消去 my $fn = $_; my @F = $fn; foreach my $FNAME (@F){ open(FILE,"$FNAME")or die "cannot open txt_file: $!";#fname.txtに記載してあるファイルを開く open(OUT,">". "new_file/$FNAME")or die "cannot write txt_file: $!";#new_fileを開いて書き込む while(<FILE>){#以下、ファイルの置換内容 my @d; if (m/^[X1-9]+ (.*)/s) { ($y,$z)=(0,0); $d[0] = ++$x; $d[1] = 0; $d[2] = 0; $_ = $d[0] . " " . $1; } if (m/^[X1-9]+\.[X1-9]+ (.*)/s) { $z=0; $d[0] = $x; $d[1] = ++$y; $d[2] = 0; $_ = $d[0] . "." . $d[1] . " " . $1; } if (m/^[X1-9]+\.[X1-9]+\.[X1-9]+ (.*)/s){ $d[0] = $x; $d[1] = $y; $d[2] = ++$z; $_ = $d[0] . "." . $d[1] . "." . $d[2] . " " . $1; } print OUT $_; } } close(IN); close(FILE); close(OUT); exit ; }

  • PERL カンマ区切り 一致行削除

    教えてくださいm(_ _)m 最初に目的を書きます・・・ ~test.txt~ 1,aaa,eee,ttt 3,eee,eee,yyy 5,ttt,yyy,eee 2,yyy,bbb,qqq ↓ 5,ttt,yyy,eee 2,yyy,bbb,qqq ~~~~~~~~~~ 例1)、カンマ区切り3列目が「eee」 の行を全て削除(完全一致) 例2)、カンマ区切り3列目が「e」を含む 行を全て削除(部分一致) というふうにしたいのですが、 どのようにするのかわからないです・・・ 現在下記のように とりあえず1行目(0番目)を削除するとこまできました。 #! /usr/bin/perl $TEST = 'test.txt'; open(FILE, "<$TEST"); eval{ flock(FILE, 1) }; @DATA = <FILE>; close FILE; $NO = 0; splice @DATA, $NO, 1; open(FILE, ">$TEST"); eval{ flock(FILE, 2) }; print FILE @DATA; close FILE;

    • ベストアンサー
    • Perl
  • Perlのエラー(絞込検索時にファイルロックが。。。

    こんにちは。よろしくお願いします。 Perlの担当者が休まれているため、急遽システムの修正~を行うことになったPerl初心者です。 Perlで作成されているシステム内の、「検索機能」の部分でエラーが出て困っています。 テキストボックスがあり、その中に文字をいれ、検索ボタンを押すと、あらかじめ登録を行っておいたデータのタイトル~にあたる部分との照らし合わせを行い、絞り込んで表示していく~ような検索機能です。 そのテキストボックスに「[」や「+」、「(」、「)」、「*」などを入力して実行させてしまうと、システムが動かなくなります。(エラー表示は無く、画面が真っ白に。 その後、そのシステムの設置フォルダと同じフォルダ内に「システムで設定した名前.txt.lock」というフォルダが作成されていて、それを削除しない限りはシステムが動きません。 原因としては、ファイルロックを行って、ファイルの中身を読み込んで、その最中に上記の検索~のための比較を行い、表示するものを格納して、ファイルロックを解除~。。。 の、比較~の部分かと思っています。 if($file[3]){ $file[3] =~ s/\ /KUGIRI_SPACE/g; $file[3] =~ s/\ /KUGIRI_SPACE/g; local @keyword = split(/KUGIRI_SPACE/, $file[3]); foreach $keyword (@keyword){ @word = split(//, $keyword); $search_keyword = shift @word; foreach $word (@word){ if($word =~ /[^a-zA-Z0-9]/){ $search_keyword .= "\\$word"; }else{ $search_keyword .= "$word"; } } if($one_log[2] !~ /$search_keyword/i){ $Agreement = "NO"; } } } if($Agreement eq "NO"){ undef $Agreement; next; } こんな感じのソースなのですが、 「if($one_log[2] !~ /$search_keyword/i)」の部分で、比較を行っているのだと思いますが。。。 この先の原因究明~が分かりません。 ファイルのロックについてや上記ソースで気になる点など、何でもかまいませんので知恵をお貸し願えませんでしょうか??

    • ベストアンサー
    • Perl
  • 行数ごとに検索をかけて並び替えをしたいのですが・・

    数千のファイル名が書かれたテキストファイルがあります。(Aとします。) /yyy/ccc.txt /aaa/aaa.txt /bbb/bbb.txt /sss/aaa.txt /ccc/bbb.txt /zzz/ccc.txt ・ ・ ・ ユニークファイル名だけ書かれたファイルがあります。(Bとします。) aaa.txt bbb.txt ccc.txt ・ ・ ・ Bの行数1行ずつAで検索をかけ、ファイル名を新しいファイル(Cとします)に書き出したいのです。 /aaa/aaa.txt /sss/aaa.txt /bbb/bbb.txt /ccc/bbb.txt /yyy/ccc.txt /zzz/ccc.txt ・ ・ ・ シェルを使ってやりたいのですが、どのようにすればいいのか見当もつきません。 どなたかお分かりのかたいましたら教えてください。よろしくおねがいします。

  • Perl 日付処理 逆

    Perl 日付処理仕組み $Tm = "1488992820"; my ($Nsec, $Nmin, $Nhour, $Ndate, $Nmon, $Nyear, $Nday) = localtime($Tm); $Nyear += 1900; $Nmon += 1; print "$Nyear/$Nmon/$Ndate"; これで結果は 2017/3/9 となりますが、 逆に 2017 3 上記の年月で 逆に戻したいのですが、 どのようにするのでしょうか? 1488992820のよう細かい日付でなくていいのですが 2017年3月内のlocationTimeに戻したいのです。 説明が下手くそなので、 実際やりたいこと・・・ ログファイル1列目に 1488992820 のように、ログ時間があり、 それをまず 月間別に分け 上記ですと 2017年3月というアンカーを作り <a href="test.cgi?Y=2017&M=3">2017年3月</a> このような感じがページに並び、 これを選択すると ページでそれに該当する行だけ配列に入れ 表示させるということです。 ブログ記事にあるアーカイブ、月間別 を作りたいです ※ログファイルに、予め 2017,3 といったように、書き込むのはなしです。 これは最終手段・・・ 無理やりではありますが value="2017,3," my $a = 0; my @DATA = grep { $DATA[$_] =~ /,2017,3,/ } 0..$#DATA; $a = scalar @DATA ; 一応実行はできております。

専門家に質問してみよう