質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Perl

Perlは多目的に使用される実用性が高い動的プログラミング言語のひとつです。

Q&A

解決済

2回答

851閲覧

perl 検索時のフラグの使い方

yabu12

総合スコア12

Perl

Perlは多目的に使用される実用性が高い動的プログラミング言語のひとつです。

0グッド

0クリップ

投稿2017/10/22 12:53

---hoge.txt---
<aaa>
hoge.a
</zzz>
<bbb>
hoge.b
</zzz>
<ccc>
hoge.c
</zzz>
<aaa>
hoge.a
</zzz>
<bbb>
hoge.b
</zzz>
<ccc>
hoge.c
</zzz>
<aaa>
hoge.a
</zzz>



繰り返し

---hoge.txt---

上記ファイルを読み込んで、「<aaa>」から対応した「</zzz>」の部分を抜き出しその部分を<xxx>と置換を行いたいです。
イメージとしては、読み込んだファイルを配列に入れて、一行づつ読ませ、キーワード「aaa」が現れたらそこでフラグを立て、またキーワード</ZZZ>が現れたらフラグを立て、その部分以外はnextで飛ばす処理を繰り返して行いたいと考えています。

---hogehoge.txt---
<xxx>
hoge.a
</xxx>
<xxx>
hoge.a
</xxx>
<xxx>
hoge.a
</xxx>


---hogehoge.txt---

のようなイメージで表示させたいのですが、
私の理解不足もあり、現状作成したスクリプトでは、うまくいきません。
そこで質問させていただきました。下記の様なスクリプトの形で作成したいと考えています。
どうかよろしくお願いいたします。

---現状作成したスクリプト---
```
use utf8;
use strict;

open(IN,"<","hoge.txt");
open(OUT,">>","hogehoge.txt")or die"error:$!";

my $flag = 0;
while (my $data = <IN>) {
if($data =~ /</zzz>/){
$flag = 0;
}elsif ($data =~ /<aaa>/){
$flag = 1;
#フラグ0と1の範囲の指定を行いたい
}elsif ($flag){
$data =~ s{</zzz>}{</xxx>}g;
$data =~ s{hoge.a}{hoge.aaa}g;
$data =~ s{<aaa>}{<xxx>}g;
print OUT $data;
}else{
next
}
}
close(IN);
close(OUT);

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

Perl - perl 検索範囲指定(95911)|teratail

上記質問の内容が参考になるかと思います。
同様にsedを用いると下記のように書けます。

bash

1sed -n '/^<aaa>$/,/^</zzz>$/p' hoge.txt | sed -e 's/^<aaa>$/<xxx>/g' -e 's/^</zzz>$/</xxx>/g' > hogehoge.txt

投稿2017/10/22 12:58

編集2017/10/22 13:08
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/10/22 13:05

質問者は同じ方でしたか。
yabu12

2017/10/22 13:16

前回はありがとうございました。 前回教えて頂いた方法で出来たはしたんですが、 メモリの関係でフラグを立てる方法で動かすにはどうするのかと思いまして、 試行錯誤はしたのですが、抜き出せず質問させていただきました。申し訳ありません。
退会済みユーザー

退会済みユーザー

2017/10/22 14:21

リソースに制約があるのであれば、実行環境等の前提について質問に含められた方が、求める回答が得られやすいかと思います。
yabu12

2017/10/22 14:55

アドバイスありがとうございます。 リソース制約に関しては、抜けていました。 今後は、気を付けて質問させて頂きたいと思います。 その際には、ぜひよろしくお願いいたします。
guest

0

ベストアンサー

elsifで繋いでしまうと、せっかく$flagを変更しても、その時の入力データについては置換・出力の処理ブロックが実行されないので、意図したような結果にならないと思います。

これは範囲指定演算子で処理するのがはるかに簡単ですが、あえてフラグ変数を使ってみたいというなら、
whileループの中はこんな感じでしょう。

perl

1while (my $data = <IN>) { 2print $flag,$data; 3 if ($data =~ /\<aaa\>/){ 4 $flag = 1; 5 } 6 7 if ($flag){ 8 $data =~ s{</zzz>}{</xxx>}g; 9 $data =~ s{hoge.a}{hoge.aaa}g; 10 $data =~ s{<aaa>}{<xxx>}g; 11 print OUT $data; 12 } 13 14 if($data =~ /\</xxx\>/){ 15 $flag = 0; 16 } 17}

ちなみに範囲演算子を使うと、

perl

1while(<IN>){ 2 if(m{<aaa>} .. m{</zzz>}){ 3 s{</zzz>}{</xxx>}g; 4 s{hoge.a}{hoge.aaa}g; 5 s{<aaa>}{<xxx>}g; 6 print OUT $_; 7 } 8}

投稿2017/10/22 13:47

KojiDoi

総合スコア13669

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yabu12

2017/10/23 11:49

ごめんなさい。昨夜、返事を送れていませんでした。 昨日はご丁寧に回答していただきありがとうございました。 目的の事を無事達成出来ました。ありがとうございます。 返事も遅れてしまい申し訳ないのですが、 真ん中のif の($flag)の条件はなんなのでしょうか。 $flagがついてるところならという認識で大丈夫なのでしょうか。 また、認識が間違っているのなら教えていただと幸いです。 申し訳ないのですが、どうかよろしくお願います。
KojiDoi

2017/10/23 16:01

if分の中身は「式の値が真か偽か」の判定となります。perlの世界では0や""や未定義は「偽」、それ以外は「真」みなされます。ここでは$flagは1か0のどちらかをとるので、実質的にif($flag==1)と書いたのと同じことです。
yabu12

2017/10/23 22:47

ifの判定の中身が知りたかったので ここでの$flagは$flag=1なら真ということですね。 ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問