• ベストアンサー

フォルダ内のファイルを全て開き文字列置換

こんばんは。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); } どなたか、ご教示いただけると非常助かります。 よろしくお願い致します。

  • Perl
  • 回答数6
  • ありがとう数5

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

  • ベストアンサー
  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答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; }

その他の回答 (5)

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.6

もうhttp://okwave.jp/qa5526745.htmlに移ってこっちは放置かもしれませんが。 わたしが#2で提示したスクリプトでは、 undef $/; という行があるのに注意してください。 これによって、「ファイルの丸呑み」ができるようになり my $content = <$fh>; で、$contentにファイルの内容が丸々入ります。 #通常は一行だけ 今回はs修飾子もm修飾子もつける必要がないので(つけても構いませんが) $content =~ s/\n{3}/\n[SAMPLE]\n/g; で望みの置換をやってくれるはずです。 もう一つの質問も基本は同じですね。

Kazu_creator
質問者

お礼

度々のご回答、誠にありがとうございます。 最初見たときはわからなかったのですが、undef $/; の部分でレコードセパレータを無効化していたのですね。 お陰で思ったとおりの処理をすることができました。 せっかくの機会なので、今後レコードセパレータを無効化するとはどういうことなのか、掘り下げて見たいと思います。 大変勉強になりました。

  • kuroizell
  • ベストアンサー率55% (95/170)
回答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を使って配列からスカラに入れてみました。

Kazu_creator
質問者

お礼

なるほど! そういうやり方もありますね。 正解にたどり着く道がひとつでないのがプログラミングの醍醐味、 と、生意気ならがら思ってしまいました。 ありがとうございました。 たいへん勉強になりました。

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

あれ? '<' で open したファイルに書き込めるんでしたっけ>#2. '<+' とかなんとかにしないといけないような....

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答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; } 試してないので間違いが入ってたらごめんなさい。

Kazu_creator
質問者

補足

サンプルリストありがとうございます。 上記では、エラーになったので以下のようにしたら、とりあえず動きました。 しかし、このやり方だと結局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);

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.1

入門書の類などはお持ちでないのでしょうか? foreach open(FILE, "$filename(@filename)") { my @content =<FILE>; @content =~ s/\n{3}/\n[SAMPLE]\n/g; いくらなんでもこれはない。としかコメントのしようがありません。 なんで foreach のすぐ後ろに open が来ていたり、 =~ の左辺が配列変数だったりするんでしょうか。 #smart matchingでもこれはないよなあ。たしか。 もうひとつ、今回の例ではファイルから読み込んだ結果を配列に収めちゃだめですね。

Kazu_creator
質問者

お礼

入門書は持っています。週末に入門書片手に独学を始めて3週目です。 この質問を書いたときは、仕事中だったので手元に入門書がなく、オンラインの入門サイトなどを斜め読みしながらコソコソとやっていました。 #2のスクリプトはのちほど試させていただきます。 >いくらなんでもこれはない。としかコメントのしようがありません。 私も翻訳の仕事をしていますので、英語の質問を見るとそういう気持ちになることがあります。 しかも、英語の場合は間違いを指摘しても、受験英語のルールに固執し、間違いを認めなかったりします。

関連するQ&A

  • 複数行に渡る文字列の置換

    こんにちは、Perl初心者です(プログラミング全般の初心者です)。 カレントフォルダ内のテキストファイルに対して、文字列置換をするスクリプトを書こうとしています。具体的には、以下のようにストリングIDの直下に改行のみの場合(ストリングがない)は、[BLANK]という文字列を挿入したいと思っています。 TEXT_STRING_ID_001<改行> <改行> <改行> TEXT_STRING_ID_002<改行> 入門書やこのサイトの皆さまのお力を借りて、なんとか以下のようなリストを書きエラーなく置換処理ができるところまでは確認できました。 しかし、この方法だと結局1行ずつ処理していることになるので、「s/\n{3}/\n[en]\n/gm」のような置換ができません(mオプションをつけてもダメなようです)。 この問題を解決する良い方法はないものでしょうか。 (もしかすると、処理の仕方を根本から変えないといけないのでしょうか) 以下、現状のリスト: 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[BLANK]\n/gm; } open(NEWFILE, "> $dir") or die "$dir: $!"; print NEWFILE @file; close(NEWFILE); } closedir(DIR);

    • ベストアンサー
    • Perl
  • ファイル名変更ができません

    こんにちは。Perl(超?)初心者です。 フォルダ内にあるファイルの名前を、「filename_ja.txt」という形式から「filename_en.txt」に変更するスクリプトを書こうとしているのですが、エラーになってうまくいきません。 環境は、Windows XP professional SP3とActivePerl 5.10 で、以下のように記述しました。 use strict; use warnings; my @filename = glob "*.txt"; foreach my $oldname(@filename) { my $newname = $oldname; $newname = ~s/(.+)_ja\.txt/$1_en\.txt/; rename ($oldname,$newname); } これを実行すると、「Use of uninitialized value $_ in substitution (s///) at test_5.pl line 8.」とエラーメッセージが出て、フォルダ内のテキストファイルが消失してしまいます。 また、以下のようにも書いてみたのですが、やはりうまくいきません。 この場合は、エラーこそ出ないものの、なにも起こりません。 use strict; use warnings; for(<\.txt>) { my $old=$_; s/(.+)_ja\.txt/$1_en\.txt/; rename($old,$_); } 初歩的な質問で申し訳ありませんが、ダメな生徒にアドヴァイスを与えるつもりで、スクリプトを添削していただけるとありがたいです。 よろしくお願いします。

    • ベストアンサー
    • Perl
  • Perl:ドイツ語のウムラウト文字の置換ができなくて困っています

    Perl初心者です。ドイツ語のウムラウト文字の置換ができなくて困っています。 環境はWindowsXP + ActivePerl v.5.8.7 です。 以下のスクリプトを実行しています。 === use strict; use warnings; use encoding 'utf8'; my $txt = "*"; print "Pre: $txt\n"; $txt =~ s/*/a/; #置換 print "After: $txt\n"; === *にアルファベットや日本語を入れたときは、"a"に置換されるのですが、 ドイツ語の"アーウムラウト"を入れると置換されません。 文字コードを調べたりしたのですが、解決策が見つからずにこまっています。 きっと、基本的なことがわかっていないのだと思います。 お助けください。

    • ベストアンサー
    • Perl
  • ファイル名を正規表現にかける際の文字コードについて

    Windows XP, ActivePerl5.8.8 です。 windows 上にあるファイルの名前に沿ってフォルダに振り分けしたく、 以下のようなコードを書きましたが、 ファイル名に日本語の「ソ」などがある場合に 処理がおかしくなります。 文字コードの問題だと思いますが、どうすれば解決できるでしょうか。 ++++ここからソース++++++ #!c:/perl/bin/perl.exe use 5.008; use strict; use warnings; use File::Basename; use File::Copy; use File::Path; my $newdir = "C:/tmp"; for my $filename ( @ARGV ){ main($filename); print "complete.\n"; } sub main{ my ($filename) = @_; my($basename, $basedir) = fileparse($filename); my($name1, $name2, $ext) = $basename =~ /^(.*) - (.*)(\.[a-zA-Z0-9]+)$/; mkdir "${newdir}/${name1}"; File::Copy::copy( "${filename}", "${newdir}/${name1}/${basename}" ) or die "${filename} : Cannot copy"; } 1;

    • ベストアンサー
    • Perl
  • フォルダ内のファイル名の末尾7文字を一括置換

    フォルダ内のファイル名の末尾7文字を一括置換 こんにちは、VBA初心者です。 D:\test フォルダに test_jp.txt、sample_jp.txt、testsample_jp.txt といった名前のファイルが格納されているとします。 これらのファイル名の「_jp.txt」の部分(末尾7文字の部分)を「_en.txt」に置換したいのですが、うまくいきません。 以下のようなプログラムを書いてみたのですが、どこがいけないのでしょうか。 ※「実行時エラー53 ファイル名が見つかりません。」となります。 ※ VBEのローカルペインによると、エラー時には filename 変数に sample_jp.txt が格納されています。 Sub ファイル名置換() Dim fileName As String fileName = Dir("D:\test\*_ja.txt") Do Until fileName = "" Name "D:\test" & fileName As "D:\test" & Left(fileName, Len(filename) - 7) & "_de.txt" filename = Dir() Loop End Sub

  • 12文字以上の単語リスト作成

    こんばんは。Perl初心者(プログラミングの初心者です)。 たびたびお世話になっております。 現在、カレントディレクトリにあるテキストファイルから12文字以上の単語を抽出し、新規テキストファイルにはき出すスクリプトを書こうとしているのですが、うまくいきません。 以下のようなリストを記述して見たのですが、どうやら12文字以上の単語が含む「行」を抽出しているようなのです(その処理自体も不安なのですが…)。 どこがいけないのか、そもそも根本的に間違っているのか、ご指摘いただけると非常に助かります。 ご助言よろしくお願いします。 use strict; use warnings; while ( my $file = glob '*.txt' ) { open my $reading, '<', $file or die; my @content = <$reading>; close $reading; my @results = grep(/[a-zA-Z']{12,}/,@content); foreach my $result (@results) { open (NEWFILE, ">LongWords_12.txt") or die "$!"; print NEWFILE @results; close(NEWFILE); } }

    • ベストアンサー
    • Perl
  • 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超初心者です。 ユーザがブラウザのフォームに名前を入力し送信したら、「入力内容はこれでいいですか」という確認画面を表示したいのですが、s///を用いる置換の部分が、どこにどう書けばよいか分かりません。 以下のスクリプトは、ファイルを読み込んでブラウザに返し表示するものです。(ちゃんとブラウザに表示されます) 具体的に、このスクリプトの中のどこにs///を書けばよいのでしょうか。ご教示ください。 sub testComment { open(IN, "./sample.htm"); @file = <IN>; close(IN); print "Content-type: text/html\n\n"; foreach (@file) { print $_; }

    • ベストアンサー
    • Perl
  • カンマ形式のテキストファイルの置換

    テキストファイルの変換に困っています. 1,2,3,4 5,6,7,8 というデータを 1 2 3 4 5 というように置換操作でカンマ→改行にしたいと 思っています. ・秀丸の場合 ,→\n(改行文字)でできます. でもメモ帳の場合は\nのようなエスケープシーケンス は使えません メモ帳で置換後の文字列を改行にしたいのですが どのようにしたらいいでしょうか?教えてください メモ帳でだめならエクセルではできないでしょうか?

  • テキストファイルを読み込み 偶数行の特定の文字を置換するには?

    お世話になります。 vb6なんですけどテキストファイルを読み込んで 偶数行のある文字を置換したいんですけど このサンプルをどういう風に改変して偶数行の文字列をある文字列に 置換するコードを書いてよいのかわかりません。 置換するのはreplace関数を使うと思うのですが。 教えて下さい。お願いします。 Dim n As Long, tmp As String n = FreeFile Open "D:\Test.txt" For Input As #n Line Input #n, tmp Close #n

専門家に質問してみよう