質問投稿でgooポイントが当たるキャンペーン実施中!!>>

当方、サーバ管理でインフラ系の経験しかなく、今回はperlでスクリプトの作成に挑戦しておりますがなかなか理解できていません。お知恵をお貸しください。

やりたいこと:
ある入力を受けたら、別ファイルに照会して特定列の文字列を抽出する。以下に例を示します。

入力が gad の場合(小文字です)、file1を参照する。例では一行目にGAD****があるのでこれに該当することとする。最終的にoffice が出力されるようにしたい。


file1の内容:
GAD93911 <test1> office
HOA14845 <test2> desk
ABC52311 <test3> chair
KFI33823 <test4> home

よろしくお願いいたします。

このQ&Aに関連する最新のQ&A

A 回答 (3件)

ファイルを開いて、各行を順番に /$in\d+\s<\w+>\s(\w+)/iでマッチするものを取り出して、それを使う・・

    • good
    • 0

サーバ管理のインフラ系って、イーサネット引いたり、HDDつけたりなのかな。

知識の度合いもわからないので、とりあえず、簡単な例です。設計条件がはっきりしていないので、的外れだと申し訳ないのですが、勝手に解釈してサンプルを示してみます。とっかかりになれば、いいのですが。

参照ファイルが
  1行1レコード
  3つのフィールドで構成されている
  フィールドセパレータは、空白文字
  行頭に空白文字は無い
と仮定します。

inter10 さんは書きました:
> ある入力を受けたら、別ファイルに照会して

ある入力は、$searchkeyに当たるかな。
別ファイルは、$searchfileに当たるのかな。

----- ここから -----
01: #!/usr/bin/perl
02:
03:$searchfile = "file1";
04:$searchkey = "gad";
05:
06:open FH, $searchfile;
07:
08:while( $l=<FH> ) {
09:  @f = split /\s+/, $l;
10:  if( $f[0] =~ /$searchkey/i ) {
11:    print $f[2], "\n";
12:  }
13:}
14:
15:close FH
16:
----- ここまで -----

プログラムの主要な行の説明は、
08: ファイルハンドラから1行取り出し、変数$lに格納。
  EOFであれば、ループから抜け出す。
09: 1行を分割して、それぞれリスト変数@fに保存する。
  セパレータは、正規表現で「空白文字1文字以上」とする。
10:第1フィールド$f[0]から検索文字を正規表現でパターンマッチ評価する。
  「$searchkeyを含む、大小文字区別なし」としている。
11:パターンがマッチした場合、第3フィールド$f[2]を出力する。

サンプルコードはインデントのため、全角スペースを使っています。こぴぺは気をつけてください。参考になれば、うれしいです。
    • good
    • 0
この回答へのお礼

お礼遅れてすみません。丁寧な解説をいただきありがとうございます!おかげさまでこちらのコードを元に、きちんと期待の動作をさせることができました!

お礼日時:2010/02/05 20:12

<test1> などはどうするのですか?

    • good
    • 0
この回答へのお礼

ご質問ありがとうございます。test* の列は特になにもせず、無視でかまいません。

お礼日時:2010/01/30 07:54

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

QPerlで特定行から特定行までを抜き出したい

皆さんのお知恵をお貸し頂ければ幸いです。

Perlで以下のようなことをしたいと考えています。
例えば、次のようなテキストファイルがあったとします。

example.log
==================================
aaaa
hogehoge
test
okok
perl
script
==================================

上記ファイルを読み込んで、「hogehoge」から「perl」の間に挟まれた行だけ抜き出したいのです。
イメージとしては、読み込んだファイルを配列に入れて、一行づつ読ませ、キーワード「hogehoge」が現れたらそこでフラグを立て、それ以降の行を表示し、キーワード「perl」が現れた時点で表示を止めるという処理になるのかな?と思っています。

このような場合、どういう風にすればいいのでしょうか?
恐れ入りますが、ご教授頂ければ幸いです。

それでは、どうぞよろしくお願い致します。

Aベストアンサー

> 一行づつ読ませ、キーワード「hogehoge」が現れたらそこでフラグを立て、それ以降の行を表示し、キーワード「perl」が現れた時点で表示を止めるという処理になるのかな?と思っています。

それでいいと思いますよ?これをそのままコード化すると、こんな感じでしょうか。(No.1さんのとはちょっと結果が違います。)

open FH, "example.log" or die $!;
$flag = 0;
while ($data = <FH>) {
  chomp $data;
  if  ($data eq "hogehoge") { $flag = 1 }
  elsif ($data eq "perl")    { $flag = 0 }
  elsif ($flag) { print "$data\n" }
}
close FH;

で、もっと略したいPerlな人だとこんな感じ。Perl独特の記法がふんだんに使われているので、勉強するには不向きかもしれませんが^^;

open FH, "example.log" or die $!;
while (<FH>) {
  print if /^hogehoge$/ .. /^perl$/ and !/^(?:hogehoge|perl)$/;
}
close FH;

※インデントに全角空白を使っているので、コピーする場合はタブなどに置換して下さい。

> 一行づつ読ませ、キーワード「hogehoge」が現れたらそこでフラグを立て、それ以降の行を表示し、キーワード「perl」が現れた時点で表示を止めるという処理になるのかな?と思っています。

それでいいと思いますよ?これをそのままコード化すると、こんな感じでしょうか。(No.1さんのとはちょっと結果が違います。)

open FH, "example.log" or die $!;
$flag = 0;
while ($data = <FH>) {
  chomp $data;
  if  ($data eq "hogehoge") { $flag = 1 }
  elsif ($data eq "perl")    { $fl...続きを読む

Q複数ファイルの読み込みについて

perl初心者です。

あるディレクトリから拡張子がdataであるファイルを全て読み込みたいのですが、方法がわかりません。
cshで書くと
foreach arg (*.data)
コマンド $arg

のようになりますが、perlだと
foreach $arg (@arg){
コマンド $arg

となりますよね?
引数がリストなのでよくわかりません。
そもそもperlではできないのでしょうか?


それともう一点ですが、ファイルオープンするときに
foreachループの中で
open(FILE, "$arg");
とすることは可能ですか?
上の質問と組み合わせて全てのファイルを開いて作業を行いたいので。

説明が下手ですいません。補足しますのでよろしくお願いします。

Aベストアンサー

while(<*.data>)
{
## $_には、*.DATAなファイル名が格納されている。
open(F,"$_"); ##openする。
while(<F>)
{
##読み出された内容が$_に格納されている。
print $_; ##出力してみる。
}
}

というのが最短コーディングです。

Q大量データから抽出する効率よいperlプログラムは

以前も質問させていただきましたが、
大量データから抽出する際の効率よいperlプログラム作成について
また、教えてください。
例)
大量データ Aファイル 3列 可変値(数値、URL、数値)タブ区切り 重複値あり
123 http://www.XX.co.jp/XX 4567
1111 http://www.XX.co.jp/XX 3333
3 http://www.XX.co.jp/YZ 4567
1111 http://www.YYY… 116

抽出対象データ Bファイル 1列(URL)重複なし
http://www.XX.co.jp/X
http://www.YYY.co.jp


BファイルにあるURLで始まるURLがAファイルにある場合 Aファイルのその行を抽出したい。
grepで実施すると すごい時間がかかってしまうため、効率よい抽出方法をおしえてください。
今回は、完全一致ではなく、Bファイルに入っているリストのURLから始まるものにしたいと考えているので、前の手法(hash連想配列)が使えないと考えております。
Aファイルが容量大きいため、grep処理では1週間たっても終わらないのです。

以前も質問させていただきましたが、
大量データから抽出する際の効率よいperlプログラム作成について
また、教えてください。
例)
大量データ Aファイル 3列 可変値(数値、URL、数値)タブ区切り 重複値あり
123 http://www.XX.co.jp/XX 4567
1111 http://www.XX.co.jp/XX 3333
3 http://www.XX.co.jp/YZ 4567
1111 http://www.YYY… 116

抽出対象データ Bファイル 1列(URL)重複なし
http://www.XX.co.jp/X
http://www.YYY.co.jp


BファイルにあるURLで始まるURLがAファイルにある場合 Aフ...続きを読む

Aベストアンサー

本当に終わるか気になったので、自分のPCで試してみました。
メモリ4Gであれこれ普通に使いながら、次のものです。
ただ、内一個は途中でやめちゃいました。

まず、こんなかんじでdummyファイルを作りました

Ruby
# dummy作成
http://ideone.com/TDxut
→1Gバイトで約2000万件の嘘データ
# フィルタ元リスト作成
→dummyの頭50件の、URL内ドメイン箇所までのリスト

Ruby
# 文字列マッチ
http://ideone.com/xPsku
→約25分

# 正規表現マッチ
http://ideone.com/kvSff
→途中でやめた為不明

GNU/grep
# grep -F -f 元リスト.txt dummy.txt
→1分弱!


ということで、少なくともRubyでは全く太刀打ちできませんでした。
でも、終わる分量ではあると思います。特にPerlならきっともっと早いんでしょう
やっぱりgrepがおすすめですね

QPerlで行頭にある文字が含まれている行を全部削除して詰めたい

perl初心者です。以下のようにデータがならんでいる時、
test111 aaaaaaaaabbbbbbbbcccccc
test112 aaaaccccabbbbbbbbcccccc
test113 aaaaccaaabbbbbbbbcccccc
test114 acccaaaaabbbbbbbbcccccc

test111 aacaaaaaabbbbbbbbcccccc
test112 accaaaaaabbbbbbbbcccccc
test113 aaacccaaabbbbbbbbcccccc
test114 aaaaaccaabbbbbbbbcccccc

test112の行だけ削除して、さらにそこを詰めたい時のスクリプトを作成しています。

途中からわかりません。
行を削除する関数が調べても見つからないのです。

#!/usr/bin/perl ;
open(IN, "test.doc") or die ;

open(OUT, ">testout.doc");

while(<IN>) {
chomp ;
if (/(\S+)/) {

$name = $1 ;

if ($name =~ /^test112(\S+)/) {
#ここでマッチさせて、一気に行を削除して、しかも行を詰めたいのですが

;

}
print OUT " \n" ;
}
}
close (IN) ;
close (OUT) ;

大変困っております。宜しくお願いします。

perl初心者です。以下のようにデータがならんでいる時、
test111 aaaaaaaaabbbbbbbbcccccc
test112 aaaaccccabbbbbbbbcccccc
test113 aaaaccaaabbbbbbbbcccccc
test114 acccaaaaabbbbbbbbcccccc

test111 aacaaaaaabbbbbbbbcccccc
test112 accaaaaaabbbbbbbbcccccc
test113 aaacccaaabbbbbbbbcccccc
test114 aaaaaccaabbbbbbbbcccccc

test112の行だけ削除して、さらにそこを詰めたい時のスクリプトを作成しています。

途中からわかりません。
行を削除する関数が調べても見つからないのです。

...続きを読む

Aベストアンサー

一致しなかったときのみ出力するということで、

while(<IN>){
unless(/^test112/){
print OUT;
}
}

更に簡単に書くと、
while(<IN>){
print OUT unless(/^test112/);
}
となります。

削除にこだわるなら、
while(<IN>){
s/^test112\s.+//;
print OUT;
}
あたりでしょうか。

もしくは、明示的に削除したいなら、
while(<IN>){
if(/^test112\s.+/){
$_ = "";
}
print OUT;
}
というふうに、カラの文字列を代入してやるのも、値を削除するときの常套手段ですね。

QPerlの正規表現で文字の抽出

Perlを勉強しているのですが正規表現についてよくわからないので教えてください。

$text="【件名】本文"

とあるときに、【】で囲まれた文字列(【】も含む)を抽出し、$textに戻したいのですがどうすればいいのでしょうか?
($textの中身を【件名】としたいのです)

よろしくお願いします。

Aベストアンサー

$1が文字化けする件に関して。
それは、日本語の半分(半角英数分のデータ)しか取り出していないからです。正規表現は日本語用に作られていないので、全角文字も半角英数として文字を処理するはずです。
$t="あいう";
@a=split(//,$t);#あいうを一文字ごとに区切り、配列にする
foreach(@a){print $_,"\n";}
を実行すれば分かります。全て文字化けし、ループは6回繰り返されます。(全角3文字=半角6文字)
一応あれは【】の中身を取り出すことのみを考えたものだったので、以下のようにすれば何とかなります。

$text='あは【件名】本文';
$text=~s/(.*)(\【.+?\】)(.*)/$2/;
print $text,"\n";

あは、を取り出したいなら2行目の$2を$1に。本文、を取り出したいなら$3に書き換えてください。正常に出来ると思われます。
ちなみに言い忘れましたが、$数字と言う変数は、本来正規表現内でのみ有効な変数です。普段は使わないように。(print $1;はエラーにはなりませんが、しない方がいいでしょう。)

$1が文字化けする件に関して。
それは、日本語の半分(半角英数分のデータ)しか取り出していないからです。正規表現は日本語用に作られていないので、全角文字も半角英数として文字を処理するはずです。
$t="あいう";
@a=split(//,$t);#あいうを一文字ごとに区切り、配列にする
foreach(@a){print $_,"\n";}
を実行すれば分かります。全て文字化けし、ループは6回繰り返されます。(全角3文字=半角6文字)
一応あれは【】の中身を取り出すことのみを考えたものだったので、以下のようにすれば何とかなりま...続きを読む

Qperlでファイル内の文字列を置換して新たなファイルに出力

3つのファイル(list1,list2,list3)を順番に読み込んで
ファイルの中のGoodという文字をBadにして
新たにlist1_new、list2_new、list_3new
という名前のファイルに書き込みたいのですが
やり方がわかりません。 下記のプログラムを
ベースに教えていただけませんか?


#! /usr/local/bin/perl

foreach LIST ( \
list1 \
list2 \
list3 \
)

open(FILE , "${LIST}" ) || die Damedame;
while (<FILE>) {
s/Good/Bad/g ;
print;
}

Aベストアンサー

foreach $LIST ( # $付ける
list1, # カンマ
list2,
list3
)
{ # foreachカッコ
open(FILE2 , ">${LIST}_new" ) or die Damedame2; # 出力用ファイルオープン
open(FILE , "${LIST}" ) or die Damedame;
while (<FILE>) {
s/Good/Bad/g ;
print FILE2 $_; # 出力処理
}
close(FILE); # クローズ
close(FILE2); # クローズ
} # foreachカッコ

Q○文字目に文字挿入

お世話になっています。
正規表現の文字置換s///gを使って数字の3桁目に-を挿入したいですが、どうしたらいいのかわかりません。

どなたか教えていただけないでしょうか。

5770001

577-0001

にしたいのでしが…

Aベストアンサー

試してないのですが
s/(.{3})(.*)/$1-$2/;
でよいはずです。

数字確定ならば\dでも可。

Qperl ファイル内文字列抽出

お世話になっております。
perlでファイルない文字データを抽出する作業をしたいですが、やり方が分からなくて、ご存知の方ぜひ教えて頂けばと思います。
001.html内の内容
<html>
<head>
</head>
<body>
テキストテキストテキストテキストテキストテキストテキストテキストテキストテキスト<img src="aaa" \/>テキストテキストテキストテキストテキストテキストテキストテキスト<img src="bbb" \/><img src="ccc" \/><img src="aaa" \/>テキストテキストテキストテキストテキストテキストテキストテキスト</body>
</html>

質問内容

(1)このなかの<img src="aaa" \/>イメージファイル名を抽出したいです。本文ではイメージファイルの拡張子はなしです。入力の間違いではないです。
(2)抽出した文字列をimg.txtファイルで出力


以上よろしくお願いします。

Aベストアンサー

ちと気になった点を突っ込ませてくださいな>#4.
my $html = join("", <IN>);
よりは
$/ = undef; my $html = <IN>;
の方がよいかと. あと,
printf(OUT "%s\n", join("\n", @src));

$" = "\n"; print OUT "@src\n";
にした方がシンプルじゃないかな.

あと open は (それなら) 3引数にするとか, そもそもリダイレクト (とコマンドライン引数) にまかせた方が簡単とかありますけどね.

Q数値かどうかの判定方法

$aに代入されているものが数値かどうかを判定するにはどのようにしたらよいのでしょうか?

Aベストアンサー

$a =~ /^[0-9]*$/
上記の場合、*は「直前のパターンの0回以上の繰り返し」の意味なので、0から9がなくても、つまり$aが空でもマッチしてしまいます。
なので、
$a =~ /^[0-9]+$/
としましょう。
(+は「直前のパターンの1回以上の繰り返し」)
また、0-9は\dで表すこともできるので
$a =~ /^\d+$/
と書くこともできます。

Qファイルの行数取得

超初心者です。

いま、表計算的なスクリプトを記述しています。

あるファイルの行数を取得する関数ってあるんでしょうか?

ファイルに記述されている数値を足したり引いたりするのですが、forを使っての計算の際にファイルの行数が必要となりました。

Aベストアンサー

Perlにですね。ないはずです。
行数とはファイルに書かれた改行文字の個数ということなので
実際にファイルを全て読み込まないと行数はわかりません。
以下のように色々な方法があると思います

#### 単純な例
$a = 0;
open FD, "<file.txt" || die $!;
while (<FD>) {
$a++;
}
close FD;
print "行数:$a\n";

### 少しマニアックな方法
open FD, "<file.txt" || die $!;
@a = <FD>;
close FD;
print "行数:" . ($#a + 1) + "\n";


### 反則的方法(外部コマンド) ... UNIXの場合
print "行数:" . `wc -l file.txt` . "\n";


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング