
こんにちは。Perlを勉強しはじめた者です。
test1.plファイルにtuika.plを起動することで追加書き込みをしようとしているのですが、
その書き込みをプログラムの途中に行おうとしています。
内容としては、test1.plが文字置換を行うもので、その候補をtuika.plで入れてやります。
tuika.pl
#!/usr/local/bin/perl
use strict;
use vars qw($oldword $newword);
print "置換元の単語は? \n";
$oldword = <STDIN>;
print "置換後の単語は? \n";
$newword = <STDIN>;
open (FH, ">>test1.pl") or die "error $!\n";
seek FH, -47, 2;
print FH "s/$oldword/$newword/og;\n";
close FH;
seek関数は実際には途中書き込みには対応していない(?)ようなので、書き込みが末尾にきてしまい、うまくいきません…。
初心者な質問で申し訳ありませんが、なにか解決策がございましたら、ご教授願います。
A 回答 (5件)
- 最新から表示
- 回答順に表示
No.5
- 回答日時:
>> seek関数は実際には途中書き込みには対応していない(?)ようなので、書き込みが末尾にきてしまい、うまくいきません…。
seek関数は操作対象になる場所を変えるだけですよ。
書き込みが末尾になるのは追記モードでファイルを開いているから。
seek使って途中を変えて意図した通りになるかはわかりませんが多分ならないのでは。
途中を変えるという事は、後ろに有効なデータが残っているという事ですよね。
置換前と置換後の文字列長が違う場合には処理が必要ですよ。
※置換後が長いと置換によって元のデータを上書きする事になる部分があるだろうし、逆だと古い文字列の一部が残るでしょうし。
要するに、長さが違う場合には別途処理が必要になるかも知れません。
No.4
- 回答日時:
>s/女性/女/og;
> ←この部分に追加していきます。
>print $ofh $_;
+>でopen→seekで移動→ファイルに出力
とすると、テキストエディタで言うところの「上書き/置換モード」になります。
うしろが自動でずれてくれる「挿入モード」ではありません。
・ずらす分を変数に取り込み→挿入する分を出力→退避していた分を出力
・全部取り込み→挿入する分を適切な箇所に挿入→全部出力
・単純な追記で済むように、方法自体を変更する
(「設定ファイル」として出力→test1.plは「設定ファイル」にしたがって置換する 等)
といった工夫が必要です。
No.3
- 回答日時:
#2 で言われているのはそういうことじゃない. 「丸ごと全部上書き」の意味が理解できていない?
余談だけど今のプログラムでひっかかるところを 2点ほど突っ込んでおこう.
1. そもそも今のパターンだと置換がうまくいかないと思うんだけど, そこは大丈夫? <STDIN> から読み込んだあとで chomp しないと, 入力を確定するための改行も入っちゃうよ.
2. その形だと s/// の o は役に立たないと思う.
No.2
- 回答日時:
">>"でオープンすると、追記しかできません。
seekするのなら、読み書き可なモード「+>」でオープンしてください。
ただし、
> seek FH, -47, 2;
これでは、SEEK_ENDから47バイト前がちょうどよい書き込み位置であるという保証はありませんし、
書き込む文字数が元より短い場合、残りは元々あった文字列が残ってしまいますので、
望み通りの結果にするのはかなり難しいと思います。
手軽に実現するなら、
・test1.pl では、冒頭で「require "test2.pl"」とでもしておく
・test1.pl では、置換そのものは「$_=test2($_);」といった形で関数呼び出しを埋め込んでおく
・tuika.pl では、test2.plを丸ごと全部上書きを行うようにする。
・test2.pl への出力内容は、「sub test2 { $_[0] =~ s/$oldword/$newword/og; }」という関数定義の形にする
といった形が楽かと思います。
この回答への補足
遅くなりまして申し訳ありません。回答ありがとうございます。
+>だと、test1.plがs/$oldword/$newword/og;だけのファイルになってしまい、悩んでいたのですが、もう一度勉強し直してきます。
Tacosan様への回答と被るのですが、
s/女性/女/og;
←この部分に追加していきます。
print $ofh $_;
}
close $ofh;
close $ifh;
}
この場合、s/$oldword/$newword/og;\n
を追加としてやれば後ろからの47バイトは動かないかなとも考えたのですが、ご指摘のとおり不安定な動作となりそうですね。
ご提示くださった手法ですが、
>>tuika.pl では、test2.plを丸ごと全部上書きを行うようにする。
>>test2.pl への出力内容は、「sub test2 { $_[0] =~ s/$oldword/$newword/og; }」という関数定義の形にする
ここは、tuika.plでtest2.plに対して「sub test2 { $_[0] =~ s/$oldword/$newword/og; }」を追加上書き保存していき、それをtest1.plで実行してやるという形ということでしょうか?
No.1
- 回答日時:
「データをファイルの途中に書き込む」のはいいとして, 元のファイルにあった「それ以降のデータ」はどうするつもり?
この回答への補足
遅くなりまして、申し訳ありません。回答ありがとうございます。
それ以降のデータといいますと、 s/$oldword/$newword/og;\n
を追加した後ろのデータのことでしょうか?
目指していたものは、置換するデータを蓄積していって、test1.plを実行した際に、一括置換するものでしたが、
while (<$ifh>) {
s/男性/男/og;
s/女性/女/og;
←この部分に追加していく感じです。
print $ofh $_;
}
この手法だとprint以下がダブったり消えたりしてしまうのでしょうか?
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
正規表現で、特定の文字列を含...
-
xmlファイル内の文字列置換
-
Eclipse 改行後のタブ
-
csvデータのダブルクォーテーシ...
-
VBA 置換文字がみつからない時
-
対称群はなぜそう呼ばれるので...
-
EXCEL警告「置換対象のデータが...
-
各項目がダブルクォーテーショ...
-
ハングルを日本語に置換
-
vbsで図形内テキストの置換方法
-
procmailで本文の文字列置換
-
EXCELマクロを用いてグラフの系...
-
C#で空白行を削除する方法
-
csvデータ ダブルクォーテ...
-
特定の列のみ置換を行いたい
-
エクセル関数 文字の置き換え...
-
秀丸マクロで、あらかじめ選択...
-
CSVファイルの中で、「 , 」カ...
-
CSVの定義
-
Excelについて質問です。 セル...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
正規表現で、特定の文字列を含...
-
VBA 置換文字がみつからない時
-
各項目がダブルクォーテーショ...
-
○文字目に文字挿入
-
csvデータ ダブルクォーテ...
-
C#で空白行を削除する方法
-
Excel・ユーザーフォームの情報...
-
csvデータのダブルクォーテーシ...
-
秀丸エディタで、「-」や「ー」...
-
フォントの色を保持したままセ...
-
Excel VBA 教えてください。 VB...
-
EXCEL警告「置換対象のデータが...
-
スペースで区切られた氏名から...
-
Eclipse 改行後のタブ
-
Excel VBA リストに一致したデ...
-
テキストボックスの文字列を置...
-
xmlファイル内の文字列置換
-
複数のパワーポイントファイル...
-
特定の列のみ置換を行いたい
-
ハングルを日本語に置換
おすすめ情報