こんばんは。Perl超初心者です(プログラミングの初心者でもあります)。
フォルダ内にあるすべてのファイルに対して、正規表現を使った文字列置換をしたいのですが、うまくいきません。アドヴァイスをいただけないでしょうか。
具体的には、あるファルダの中に100個程のファイルがあって、その中の改行が3回連続している部分を、「改行+[SAMPLE]+改行」に置換をしたいと表います。
Windows XP Professional SP3 / ActivePerl 5.10 の環境で、以下のように記述したのですが、「Missing $ on loop variable at insert.pl line 5.」とエラーになってしまいます。どこで、間違ったのでしょうか(というか、まるでダメなスクリプトかもしれませんが…)。
use strict;
use warnings;
my @filename = glob "*.txt";
foreach open(FILE, "$filename(@filename)") {
my @content =<FILE>;
@content =~ s/\n{3}/\n[SAMPLE]\n/g;
print FILE @content;
close(FILE);
}
どなたか、ご教示いただけると非常助かります。
よろしくお願い致します。
No.4ベストアンサー
- 回答日時:
寝る直前に書いたので寝ぼけてました。
こんな感じでどうでしょう。
わからないところがあれば遠慮なく質問してください>質問者様
use strict;
use warnings;
use feature ':5.10';
use strict;
use warnings;
undef $/;
foreach my $file (glob '*.txt') {
open my $rfh, '<', $file or next;
my $tmp = "$file" . "tmp";
open my $wfh, '>', $tmp or die;
my $content = <$rfh>;
$content =~ s/\n{3}/\n[SAMPLE]\n/g;
print $wfh $content;
close $rfh;
close $wfh;
#unlink "${file}.bak"
rename $file, "${file}.bak";
rename $tmp, $file;
}
No.6
- 回答日時:
もう
http://okwave.jp/qa5526745.htmlに移ってこっちは放置かもしれませんが。わたしが#2で提示したスクリプトでは、
undef $/;
という行があるのに注意してください。
これによって、「ファイルの丸呑み」ができるようになり
my $content = <$fh>;
で、$contentにファイルの内容が丸々入ります。
#通常は一行だけ
今回はs修飾子もm修飾子もつける必要がないので(つけても構いませんが)
$content =~ s/\n{3}/\n[SAMPLE]\n/g;
で望みの置換をやってくれるはずです。
もう一つの質問も基本は同じですね。
度々のご回答、誠にありがとうございます。
最初見たときはわからなかったのですが、undef $/; の部分でレコードセパレータを無効化していたのですね。
お陰で思ったとおりの処理をすることができました。
せっかくの機会なので、今後レコードセパレータを無効化するとはどういうことなのか、掘り下げて見たいと思います。
大変勉強になりました。
No.5
- 回答日時:
勉強がてらやってみました。
use strict;
use warnings;
while ( my $file = glob '*.txt' ) {
open my $in, '<', $file or die;
my @contents = <$in>;
close $in;
my $content = join('', @contents);
open my $out, ">$file";
print $out map { s/\n{3}/\n\n[SAMPLE]\n/g; $_ } $content;
close $out;
}
FHをいきなりスカラに読み込むと最初の一行だけしか代入されず、mapは一行ごとに処理するらしく「連続した改行」が認識されず。
という事で、joinを使って配列からスカラに入れてみました。
なるほど!
そういうやり方もありますね。
正解にたどり着く道がひとつでないのがプログラミングの醍醐味、
と、生意気ならがら思ってしまいました。
ありがとうございました。
たいへん勉強になりました。
No.2
- 回答日時:
とりあえずこんな感じかな。
手抜きですが。
use strict;
use warnings;
undef $/;
foreach my $file (glob '*.txt') {
open my $fh, '<', $file or next;
my $content = <$fh>;
$content =~ s/\n{3}/\n[SAMPLE]\n/g;
print $fh $content;
close $fh;
}
試してないので間違いが入ってたらごめんなさい。
この回答への補足
サンプルリストありがとうございます。
上記では、エラーになったので以下のようにしたら、とりあえず動きました。
しかし、このやり方だと結局1行ずつ処理しているので、「\n{3}」の部分がちゃんとヒットしてくれません(/mオプションで複数行の検索にしてもうまくいきません)。私が検索したいのは、次のような部分です。
SAMPLE_STRING_ID_001<改行>
<改行>
<改行>
つまりIDの下に改行のみの場合は、[SAMPLE]という文字列を入れたいのです。
この問題を解決する良い方法はないでしょうか。
以下、現状のリスト:
use strict;
use warnings;
my $dirname = '.';
opendir(DIR, $dirname) or die "$dirname: $!";
while (my $dir = readdir(DIR)) {
next unless (-f $dir);
next unless ($dir =~ /\.txt$/);
print $dir, "\n";
open(FILE, $dir) or die "$dir: $!";
my @file = <FILE>;
close(FILE);
foreach my $line (@file) {
$line =~ s/\n{3}/\n[SAMPLE]\n/gm;
}
open(NEWFILE, "> $dir") or die "$dir: $!";
print NEWFILE @file;
close(NEWFILE);
}
closedir(DIR);
No.1
- 回答日時:
入門書の類などはお持ちでないのでしょうか?
foreach open(FILE, "$filename(@filename)") {
my @content =<FILE>;
@content =~ s/\n{3}/\n[SAMPLE]\n/g;
いくらなんでもこれはない。としかコメントのしようがありません。
なんで foreach のすぐ後ろに open が来ていたり、
=~ の左辺が配列変数だったりするんでしょうか。
#smart matchingでもこれはないよなあ。たしか。
もうひとつ、今回の例ではファイルから読み込んだ結果を配列に収めちゃだめですね。
入門書は持っています。週末に入門書片手に独学を始めて3週目です。
この質問を書いたときは、仕事中だったので手元に入門書がなく、オンラインの入門サイトなどを斜め読みしながらコソコソとやっていました。
#2のスクリプトはのちほど試させていただきます。
>いくらなんでもこれはない。としかコメントのしようがありません。
私も翻訳の仕事をしていますので、英語の質問を見るとそういう気持ちになることがあります。
しかも、英語の場合は間違いを指摘しても、受験英語のルールに固執し、間違いを認めなかったりします。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・人生のプチ美学を教えてください!!
- ・10秒目をつむったら…
- ・あなたの習慣について教えてください!!
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・【大喜利】【投稿~9/18】 おとぎ話『桃太郎』の知られざるエピソード
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
perlにおけるファイルコピー方法
-
Firefox で file:// で始まる U...
-
perl ファイルが開かない
-
XML::Parserの parsefileの結果...
-
Perlで特定行から特定行までを...
-
VBAでCSVファイルの特定行を書...
-
batファイルでrenameができませ...
-
エクセルVBA コードが同じでも...
-
ExcelをCSV書き出す場合のシー...
-
ifstream/ofstream について
-
VBAでCSVファイルを途中行まで...
-
fopenでディレクトリ内の全ファ...
-
chdirがうまくできない
-
open中のファイルをrename
-
FindFirstFileとFindNextFileで...
-
ファイル名を複数個配列で確保...
-
VBAでタブ区切りテキストの保存...
-
makefileでファイルをコピー(...
-
sprintfについて
-
openした後、closeしないでプロ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
python renameについて
-
window.open でのファイル指定方法
-
MATLABのm-fileについて
-
fgets で値が取得できない
-
csvファイルの横方向への改行に...
-
巨大なテキストの最終行を取得...
-
Firefox で file:// で始まる U...
-
JSP URLに表示される拡張子 .jsp
-
重複ファイル名ある場合ファイ...
-
ファイルの存在の有無を確かめ...
-
ファイル全てを .xlsm に変更し...
-
PerlでのUseless use...
-
行を指定して削除する方法PERL
-
VBA テキストファイルを読み取...
-
HTMLのフォームで画像と文...
-
perl ファイルが開かない
-
並び方、
-
read() on unopened filehandle...
-
drtファイルはどうしたら開...
-
VBAコードを張り付け後のエクセ...
おすすめ情報