AKB48の推しメンをセンターにできちゃうかもしれない!? >>

お世話になっております。
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ファイルで出力


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

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

A 回答 (5件)

ちと気になった点を突っ込ませてくださいな>#4.


my $html = join("", <IN>);
よりは
$/ = undef; my $html = <IN>;
の方がよいかと. あと,
printf(OUT "%s\n", join("\n", @src));

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

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

ご回答ありがとうございました。
頂いた内容で推進させて頂きたいと思います。

お礼日時:2010/12/22 10:21

こんな感じですかね。


コードを見比べてみてください。
インデントは全角スペースになっています。


#!/usr/bin/perl
use strict;

open(IN, "001.html") or die "ファイルが開けない";
open(OUT, "> img.txt") or die "ファイルが開けない";
my $html = join("", <IN>);

my @src = ($html =~ /<img[^>]+src="(.+?)"/g);
@src = &uniq(@src);
printf(OUT "%s\n", join("\n", @src));

sub uniq {
 my %h;
 return grep{
  if(not defined $h{$_}){
   $h{$_} = 1;
   1;
  }
 } @_;
}
    • good
    • 0
この回答へのお礼

ご回答頂きまして誠にありがとうございました。
皆さまから教えて頂いた案を参考した上、何とかクリアできました。

今後ともよろしくお願いします。

お礼日時:2010/12/22 14:48

「部分しか抽出できなかった」「上手くいけなかった」と書かれていますが, これでは何がどう「部分しか抽出できなかった」「上手くいけなかった」のかが分かりません.


・どのような入力に対して
・どのような結果を期待して
・(その期待に反し) 実際の結果はどうであったのか
をきちんと書いてください.

前半は「少なくとも方針はあっている」と思います. 後ろの方は何を表示させたいのかわかりませんが.
    • good
    • 0
この回答へのお礼

度々お手数おかけしまして申し訳ございませんでした。

お礼日時:2010/12/22 14:49

「やり方が分からなくて」ということだから「やり方」だけ:


1. ファイルを読み込む. $/ を undef にしてから読み込むとファイル全体を一気に読み込めて楽 (だけどメモリが足りなくなったら知らない).
2. その中から img タグを取り出す. 正規表現を使うのが自然か.
3. さらに「イメージファイル名」を取り出す. ここもやっぱり正規表現を使うところだろう.
4. 必要な「イメージファイル名」を出力.

ちなみに重複したものを 1つにまとめるのはハッシュを使うのがセオリー.

この回答への補足

ご回答ありがとうございました。
以下のように抽出だけできるかどうかを書いてみました
use strict;

my $temp="";

while(<>){
my $line=$_;

if($line=~/<img src="(.*?)" \/>/){
my $img=$1;
$temp .= "$img\n";
}
}
print $temp;
部分しか抽出できなかったのはどこか間違っているでしょうか?
また重複を避けるperlも書いてみましたが上手くいけなかった
use strict;

my $Key="";
my %Buf=();

while(<>){
my $line=$_;

# キーが含まれている行なら
if ( $line =~ /<img src="(.*?)">$/ )
{
$Key = $1;
if ( defined( $Buf{ $Key } ) )
{
next;
}

print $line;

$Buf{ $Key }++;
}
else
{
print $line;
}
}

補足日時:2010/12/21 15:26
    • good
    • 0
この回答へのお礼

目的はっきり言わなくて申し訳ございませんでした

お礼日時:2010/12/22 14:50

(1) 「このなかの<img src="aaa" \/>イメージファイル名を抽出したいです」とはどういうことでしょうか? 特に「イメージファイル名」が何 (どこ) を意味するのか分かりません. あと, / の前に変なものが入ってるんだけどそれも本当にあるの?


(2) 「img.txtファイルで出力」とは? 「img.txt ファイル『に』出力」ですか?

この回答への補足

(3)抽出されたイメージファイル名が重複された場合は1つだけ残す。

補足日時:2010/12/21 12:59
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。

>(1) 「このなかの<img src="aaa" \/>イメージファイル名を抽出したいです」とはどういうことでしょうか? 特に「イメージファイル名」が何 (どこ) を意味するのか分かりません. あと, / の前に変なものが入ってるんだけどそれも本当にあるの?
<img src="aaa" \/>⇒<img src="aaa" />となります。
作業の目的はhtmlに使われているファイルとイメージフォルダ内ファイルが一致しているかどうかをチェックするため、html内イメージファイルを抽出したいのです。
>(2) 「img.txtファイルで出力」とは? 「img.txt ファイル『に』出力」ですか?
「img.txt ファイル『に』出力」したいです。

下手な日本語で申し訳ございませんでした。
よろしくお願いします。

お礼日時:2010/12/21 12:11

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

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

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

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

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

QPerlで別ファイルから文字列の抽出

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

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

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


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

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

Aベストアンサー

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

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...続きを読む

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カッコ

QPerlで変数を使用した置換ができない

ファイル内の「1 2 3 4 5」などの数字の箇所を、「1回 2回 3回 4回 5回」のように、「回」をつけた形に変えることを考えています。
以下のようなスクリプトを書きましたが、うまくいきません。

# 「$search_replace」の参照先のテキストファイルの内容
(\d) タブ記号 $1回


EOF

# 問題のスクリプト(一部)
chomp($search_replace);
(my $search, my $replace) = split(/\t/, $search_replace);
$string[$i+1] =~ s/$search/$replace/g; #ここが問題と思われる箇所

ほしい結果は右のとおり。「1回 2回 3回 4回 5回」
現実の結果は右のとおり。「$1回 $1回 $1回 $1回 $1回」

置換文字列の$1の部分がうまく展開(?)できないようです。
どうすればよいか、ご教示ください。

Aベストアンサー

正規表現の置換部はダブルクォート文字列と同様に評価されるので、次の2つの文は同じように機能します。質問のケースでは、変数を2重に置き換えなければならないので、明示的にダブルクォートが必要になります。

$string[$i+1] =~ s/$search/$1回/g;
$string[$i+1] =~ s/$search/"$1回"/eg;

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;
}
というふうに、カラの文字列を代入してやるのも、値を削除するときの常套手段ですね。

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でディレクトリ名だけを取得したいのですが、
なかなかうまい方法が見つかりません。
ファイル名を取得する・・・というのは結構あるのですが、
ディレクトリ名だけ、というのがどうもわかりません。

ちなみにファイル名取得は以下のようにやっています。
my $md;
opendir(DIR, 'q');
while (defined($dir = readdir(DIR))) {
$md=substr($dir,0,6);
}
closedir(DIR);

ディレクトリ名だけを取得・・・というのはどうやればよいのでしょうか。

Aベストアンサー

ファイル名の取得で例示されているものは、ファイル名だけの取得できてませんよね?
質問者さんが書かれているスクリプトだと、
DIRの中にある「何か」の「たまたま」一番最後に入っていたものの「0文字目~6文字目」までを取得するスクリプトになっているのわかりますか?

my @file;
my @directory;
my $check_dir = "./q/";
$ct =0;
opendir(DIR,$check_dir);
while( defined($temp=readdir(DIR))){
#カレントディレクトリまたは上位ディレクトリの場合はパス
if( $temp eq '.' || $temp eq '..' ){ next;}
#ファイルの場合
if( -f $check_dir.$temp ){
push @file, $temp;
}
#ディレクトリの場合
if( -d $check_dir.$temp ){
push @directory, $temp;
}
}

$check_dirに設定されているディレクトリに格納されているファイルは@fileに、ディレクトリは@directoryに格納されます。

ファイル名の取得で例示されているものは、ファイル名だけの取得できてませんよね?
質問者さんが書かれているスクリプトだと、
DIRの中にある「何か」の「たまたま」一番最後に入っていたものの「0文字目~6文字目」までを取得するスクリプトになっているのわかりますか?

my @file;
my @directory;
my $check_dir = "./q/";
$ct =0;
opendir(DIR,$check_dir);
while( defined($temp=readdir(DIR))){
#カレントディレクトリまたは上位ディレクトリの場合はパス
if( $temp eq '.' || $temp eq '..' ){...続きを読む

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ファイルからデータを読み込んで、配列に格納する方法

データファイル grep.dat があり、その中は
12345
67890
ABCDE
(EOF)
となっています。
 
このファイルの中身を読み込んで、配列 P[0]の
中に("12345","67890","ABCDE") に格納したい
のですが、どのように記述すればよいでしょうか。

Aベストアンサー

多次元配列に代入する場合

my @p;
open FILE, "grep.dat";
  @{$p[0]} = <FILE>;  ・・(a)
close FILE;

openの書式などは好みで変えてください。
結論を言えば、(a)のように書けばokです。

#細かい書式は他にもありますので調べてみるといいかもしれません。

Q現在のディレクトリパスを取得するには!?

perlにて現在のディレクトリパスを取得するにはどのようにすればいいのでしょうか?
モジュールをつかってcwd()で取得できるようなのですが、モジュールが入っていないサーバでも動くようにしたいのですがうまくできません・・・
どなたかご存知でしたら教えてください。

Aベストアンサー

if($^O eq "MSWin32"){
$cwd=`cd`;
} else {
$cwd=`pwd`;
}
print $cwd;
--------------
ぐらいでいいんじゃないでしょうか


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

人気Q&Aランキング