ウォーターサーバーとコーヒーマシンが一体化した画期的マシン >>

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) ;

大変困っております。宜しくお願いします。

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

A 回答 (3件)

一致しなかったときのみ出力するということで、



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

この回答への補足

有り難うございました。
早速以下のスクリプトで実行してみたのですが、
困ったことに、test112は消えず、しかも改行されていたものが改行されずに打ち出されてしまいました。
どこに問題があるのでしょうか?
もう一度教えて頂きたいのですが。
宜しくお願いします。

open(IN, "test1109.txt") or die ;

open(OUT, ">aftertest1109");

while(<IN>) {
chomp ;
if (/(\S+)/) {

$name = $1 ; #

unless ($name =~ /^test112/) {


}
print OUT;
}
}
close (IN) ;
close (OUT) ;

補足日時:2004/11/09 17:13
    • good
    • 0

#2です。



>早速以下のスクリプトで実行してみたのですが、
>困ったことに、test112は消えず、しかも改行されていたものが改行されずに打ち出されてしまいました。

まず、test112が消えないのは、print文が、unlessブロック内に入っていませんね。
次に、改行されないのは、chompしたなら、出力時につけてやらないといけませんから、

print OUT "$_\n";

としなくてはなりませんね。

この回答への補足

できました~~~~~~~!!!!
(*^.^*)
有り難うございましたーーーーーーーー!
本当に助かりました。明日までにできないと困ることになってました。また、ちょくちょく質問させて頂くことになるかとは思いますが、宜しくお願いします。

補足日時:2004/11/09 19:48
    • good
    • 0

 行を削除する関数はありません。


 一度すべてデータを読み込み、"test112" で始まる行を出力しないことで削除を行います。
    • good
    • 0

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

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

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

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

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

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

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 $_; ##出力してみる。
}
}

というのが最短コーディングです。

QPerlで空白行を削除

現在、Perlにて外部のcsvファイルを読み込み、"重複行"と"空白行"を削除するプログラムを作成しています。
重複行を削除する部分は
------
open(IN, "csvtime.csv");
@data = <IN>;
close(IN);

@data = grep {!$count{$_}++} @data;

open(OUT, "> csvtime.csv");
print(OUT @data);
close(OUT);
------
でできたのですが、空白行を削除する部分がわかりません。
申し訳ないのですが、お教えいただけないでしょうか。

また、空白行で最初の空白行は残すようにしたいです。
よろしくお願いいたします。

例)
読み出しデータ
-----
(ヘッダ1行目)
(ヘッダ2行目)
(ヘッダ3行目)
(必要な空白)
(ヘッダ4行目)
00:00:00,302
00:01:00,274
00:02:00,272
00:03:00,248


00:04:00,237
00:05:00,239
00:05:00,239
00:06:00,256

00:07:00,260
00:08:00,250
00:09:00,253
00:10:00,241
-----

加工後データ
-----
(ヘッダ1行目)
(ヘッダ2行目)
(ヘッダ3行目)
(必要な空白)
(ヘッダ4行目)
00:00:00,302
00:01:00,274
00:02:00,272
00:03:00,248
00:04:00,237
00:05:00,239
00:06:00,256
00:07:00,260
00:08:00,250
00:09:00,253
00:10:00,241
-----

現在、Perlにて外部のcsvファイルを読み込み、"重複行"と"空白行"を削除するプログラムを作成しています。
重複行を削除する部分は
------
open(IN, "csvtime.csv");
@data = <IN>;
close(IN);

@data = grep {!$count{$_}++} @data;

open(OUT, "> csvtime.csv");
print(OUT @data);
close(OUT);
------
でできたのですが、空白行を削除する部分がわかりません。
申し訳ないのですが、お教えいただけないでしょうか。

また、空白行で最初の空白行は残すようにしたいです。
よろしくお願いいたします。

例)
読...続きを読む

Aベストアンサー

あれ、このコードで空白行削除されませんか?

読み出しファイルの「(必要な空白)」って最初の空白行ですよね?

>@data = grep {!$count{$_}++} @data;
これはハッシュに存在しないものだけ配列に格納してるんで、最初の空白行だけに整形されるはずですが。

空白行にひとつ以上のタブや半角・全角スペース文字が来たりしてたら動作しないとは思いますが。

Qファイルを1行削除する

ゲストブックに削除機能を付けたいのですが、やり方がわかりません。
入力された番号と一致する行を探し出して、削除キーと入力された番号が
同じだったら削除、としたいのですが、ファイルの一行を削除する方法がわかりません。
どのように行えば良いのでしょうか?

Aベストアンサー

原始的ですが、以下の方針が考えられます。

・ファイルの内容を一行ずつ読み込む
 ・削除対象となる行かどうかのチェック
  ・削除対象の行なら、次の行へ
  ・削除対象でなければ、行の内容を変数に格納
・全ての行をチェックし終えたら、変数に格納した
 情報だけを元のファイルに上書きする。

これは、効率は悪いのですがとりあえず使えます。
ちなみに、Tempファイルを使う方式だと
「削除対象でなければ、行の内容を変数に格納」
しないで、ファイルに追記することになります。
(全部終わったら、Tempファイルと元のファイルを
置き換えて、Tempファイルを削除します)

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

Q数値かどうかの判定方法

$aに代入されているものが数値かどうかを判定するにはどのようにしたらよいのでしょうか?

Aベストアンサー

$a =~ /^[0-9]*$/
上記の場合、*は「直前のパターンの0回以上の繰り返し」の意味なので、0から9がなくても、つまり$aが空でもマッチしてしまいます。
なので、
$a =~ /^[0-9]+$/
としましょう。
(+は「直前のパターンの1回以上の繰り返し」)
また、0-9は\dで表すこともできるので
$a =~ /^\d+$/
と書くこともできます。

QPerlでファイルの列を削除する。

どのように書けばいいかわからないので教えてください。
","で区切られたcsvファイルがあるとします。(file.csv)
そのファイルは全部で5列ありますが、4列目と5列目は値が入っている場合と無い場合があります。(1~3列目は必ず値は存在します。)
このファイルの1列目と2列目を削除して、3列目から5列目だけのファイルを作成したいのですが、どうすればいいのでしょうか?

よろしくお願いします。

Aベストアンサー

$line='a,b,c,d,,f';
($first, $second, $rest) = split(/,/,$line,3);
print $rest;
みたいにすれば、3列目以降を$restにとりだせます。
3列目以降に値が入っていない列があっても大丈夫です。

Qsedの置換文字に変数を使用したいのですが・・・

あるファイルの特定の文字を変換し、上書きをする処理を行いたいのですが、sedの置換文字に変数が渡せなくて困っています。

例:
X="a"
Y="b"
echo test.txt | sed 's/${X}/${Y/g}' >test.txt

sedでは置換文字に${X}といった変数を使用することはできないのでしょうか?

Aベストアンサー

' ・・・' で囲まれた中の$はそのままドルマークです。変数展開をするなら、'・・・'で囲んではいけません。

何も囲まないか、"・・・"で囲むかです。

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";

QPerlの正規表現で文字の抽出

Perlを勉強しているのですが正規表現についてよくわからないので教えてください。

$text="【件名】本文"

とあるときに、【】で囲まれた文字列(【】も含む)を抽出し、$textに戻したいのですがどうすればいいのでしょうか?
($textの中身を【件名】としたいのです)

よろしくお願いします。

Aベストアンサー

$1が文字化けする件に関して。
それは、日本語の半分(半角英数分のデータ)しか取り出していないからです。正規表現は日本語用に作られていないので、全角文字も半角英数として文字を処理するはずです。
$t="あいう";
@a=split(//,$t);#あいうを一文字ごとに区切り、配列にする
foreach(@a){print $_,"\n";}
を実行すれば分かります。全て文字化けし、ループは6回繰り返されます。(全角3文字=半角6文字)
一応あれは【】の中身を取り出すことのみを考えたものだったので、以下のようにすれば何とかなります。

$text='あは【件名】本文';
$text=~s/(.*)(\【.+?\】)(.*)/$2/;
print $text,"\n";

あは、を取り出したいなら2行目の$2を$1に。本文、を取り出したいなら$3に書き換えてください。正常に出来ると思われます。
ちなみに言い忘れましたが、$数字と言う変数は、本来正規表現内でのみ有効な変数です。普段は使わないように。(print $1;はエラーにはなりませんが、しない方がいいでしょう。)

$1が文字化けする件に関して。
それは、日本語の半分(半角英数分のデータ)しか取り出していないからです。正規表現は日本語用に作られていないので、全角文字も半角英数として文字を処理するはずです。
$t="あいう";
@a=split(//,$t);#あいうを一文字ごとに区切り、配列にする
foreach(@a){print $_,"\n";}
を実行すれば分かります。全て文字化けし、ループは6回繰り返されます。(全角3文字=半角6文字)
一応あれは【】の中身を取り出すことのみを考えたものだったので、以下のようにすれば何とかなりま...続きを読む


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

人気Q&Aランキング