親子におすすめの新型プラネタリウムとは?

ファイル内の「1 2 3 4 5」などの数字の箇所を、「1回 2回 3回 4回 5回」のように、「回」をつけた形に変えることを考えています。
以下のようなスクリプトを書きましたが、うまくいきません。

# 「$search_replace」の参照先のテキストファイルの内容
(\d) タブ記号 $1回


EOF

# 問題のスクリプト(一部)
chomp($search_replace);
(my $search, my $replace) = split(/\t/, $search_replace);
$string[$i+1] =~ s/$search/$replace/g; #ここが問題と思われる箇所

ほしい結果は右のとおり。「1回 2回 3回 4回 5回」
現実の結果は右のとおり。「$1回 $1回 $1回 $1回 $1回」

置換文字列の$1の部分がうまく展開(?)できないようです。
どうすればよいか、ご教示ください。

A 回答 (5件)

正規表現の置換部はダブルクォート文字列と同様に評価されるので、次の2つの文は同じように機能します。

質問のケースでは、変数を2重に置き換えなければならないので、明示的にダブルクォートが必要になります。

$string[$i+1] =~ s/$search/$1回/g;
$string[$i+1] =~ s/$search/"$1回"/eg;
    • good
    • 1
この回答へのお礼

なるほど、よくわかりました。
ありがとうございました。

お礼日時:2014/05/23 12:15

>ただ、質問に対する回答としてはズレがあるのではないかと思います。


 と言われても、
>>ファイル内の「1 2 3 4 5」などの数字の箇所を、「1回 2回 3回 4回 5回」のように、「回」をつけた形に変えることを考えています。
 だったらいちいち配列やハッシュに入れる必要はないかと・・

 もうすこし具体的にオリジナルデータ中に、ぽつんと「1\t2\t3\t4\t5」とあるのか、詳しい説明がないと・・

1_挨拶とオリエンテーション
2_カリキュラムの紹介、HTMLとは
・・・とか
    • good
    • 0

次のようにすれば、置き換えられるかも?



$string[$i+1] =~ s/$search/qq(\"$replace\")/eeg;

この回答への補足

ありがとうございました。置換文字列を「式」とみなす(evaluation)ことを2回繰り返しているのですね。ただ、ここでの$replaceが、どのようにして最終的な展開形となるのか、うまく自分の頭のなかで説明できません。qq( ) と、" " がどのように機能している(「"」がエスケープされている理由も含めて)のでしょうか。

補足日時:2014/05/22 17:02
    • good
    • 1
この回答へのお礼

ありがとうございました。無事、動きました。
もしよろしければ、補足入力もご覧いただければと思います。

お礼日時:2014/05/22 17:02

(my $search, my $replace) は2値の配列なのに、元データは??


chomp($search_replace);
my $separator = "\t";
my $newSeparator = "回";
$search_replace =~s/$separator/$newSeparator/g;
print $search_replace,$newSeparator,"\n";


とか
chomp($search_replace);
my $separator = "\t";
my $newSeparator = "回";
my @data = split(/$separator/, $search_replace);
while(<@data>){
print $_,$newSeparator;
}
print "\n";
    • good
    • 0
この回答へのお礼

ありがとうございました。ただ、質問に対する回答としてはズレがあるのではないかと思います。

お礼日時:2014/05/22 17:01

えばる

    • good
    • 0
この回答へのお礼

ありがとうございました。鈍感な私では、それがevaluationのことだとはわかりませんでした。

お礼日時:2014/05/22 17:00

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

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

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

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

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

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

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

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

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

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

Aベストアンサー

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

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

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

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

Aベストアンサー

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

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で以下のようなことをしたいと考えています。
例えば、次のようなテキストファイルがあったとします。

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でパターンマッチを行う際、正規表現で行いますが、パターン文字列内に変数を指定したい場合はどうすればよいのでしょうか?

if ($ENV{HTTP_USER_AGENT} =~ /$pattern/) {
 :
}

というようなことをしたいのですが、うまくいきません。
方法はありますでしょうか?

Aベストアンサー

$dat = 'abcdefg';
$pattern = 'cde';

if($dat =~ /$pattern/){ print "01\n";}
if($dat =~ $pattern){ print "02\n";}

結果
01
02

普通にマッチしますよ。
$patternの内容に問題あるのでは?
内容を再度確認してみてください。

Qサブルーチンを認識しません。

perlプログラムで
サブルーチンの中で、別のサブルーチンを呼び出していますが、
なぜか認識しません。
KCatchでは以下の表示をしています。
Catch: Mon Sep 22 07:56:36 2003
-------------------------------------------------
[regist.cgi:375:die] Undefined subroutine &main::lock called.
>&lock;
-------------------------------------------------
regist.cgi with Perl 5.00502 for freebsd

サブルーチン名には頭に & を付けて呼び出しています。
サブルーチンは、スクリプトの最後にまとめてあります。
同じサブルーチンは、他のスクリプトでも利用していますが、
エラーは出ていないのですが。

何が原因か、わかりません。
関係ないかもしれませんが、プログラム最初の方でuse strict;の宣言をしています。
他のサブルーチンも認識しません。
KCacthの表示は同じ
&main::サブルーチン名 called になっています。
よろしくお願いします。

perlプログラムで
サブルーチンの中で、別のサブルーチンを呼び出していますが、
なぜか認識しません。
KCatchでは以下の表示をしています。
Catch: Mon Sep 22 07:56:36 2003
-------------------------------------------------
[regist.cgi:375:die] Undefined subroutine &main::lock called.
>&lock;
-------------------------------------------------
regist.cgi with Perl 5.00502 for freebsd

サブルーチン名には頭に & を付けて呼び出しています。
サブルーチンは、スクリプト...続きを読む

Aベストアンサー

下記前提でよいでしょうか。
&lock(); ・・・(lockを呼び出している箇所)

sub lock    ・・・サブルーチン:lockの定義
{
・・・
}
上記は1つのソースファイル上にある。

とすると、考えられるのは、
1.undef (&lock); により未定義にしている。
2.__DATA__のあとにsub lockを定義している為、サブルーチンとして認識されない。(__END__も同様)
です。上記の2点はOKでしょうか?

Qひとつの命令を複数行に記述

検索してもあまり解説見かけないなぁと思うのですが、(どこが本家かわからないのでとりあえず放置)

VBでいう_に該当するものは何ですか?
ソースが長くなって見にくくなっているので、対処したいのですが。

hoge = "じゅげむじゅげむごごうのすりきれ" _ '←次の行に送る
& "かいじゃりすいぎょのうんらいまつふうらいまつすいぎょうまつ" 

Aベストアンサー

Perlは、VBと異なり行の概念がありません。
VBではステートメント区切り子が存在しないため、改行がステートメントの区切りとして扱われ、例外的につなげるときに「_」を使うわけですが、
Perlの場合はステートメント区切り子セミコロン「;」がステートメントの区切りになっていますので、セミコロンを打たない限り、何行に分かれてもひとつのステートメントとして扱われます。
したがって、回答としては「そのまま改行してOK」です。
上記の例なら、

$hoge = "じゅげむじゅげむごごうのすりきれ" .
"かいじゃりすいぎょのうんらいまつふうらいまつすいぎょうまつ";

という感じです。
当然ながら、文字列中での改行はダメなので、上記のようにいったん「"」を閉じて、文字列結合演算子「.」で接続することに成ります。

Qダブルクォーテーションの削除(置換)

$a = qq/"aaaaaa","bbbbb"/;
print $a;
→ "aaaaa","bbbbb"

としたときの、変数 $a の中にある
ダブルクォーテーションを削除したいのですが、

$a =~ s/"//;
では何も変化が無くて、

$a =~ tr/"/ /;
では半角スペースに置換できるのですが、

$a =~ tr/"//;
では何も変化がありません。

上手く出来る方法はどの様な方法でしょうか?
教えていただければありがたいです。

よろしくお願いいたします。

Aベストアンサー

$a =~ s/"//;
とした時には
→aaaaa","bbbbb"
という風に一つ目の「"」だけは無くなっていませんか?
$a =~ s/"//g;
とすれば全ての「"」を削除できます。

また、tr///を使う時には、
$a =~ tr/"//d;
とすれば変換先リストに無い文字を削除できます・

参考URL:http://homepage2.nifty.com/sak/w_sak3/doc/sysbrd/pe_k08.htm

Q現在のディレクトリパスを取得するには!?

perlにて現在のディレクトリパスを取得するにはどのようにすればいいのでしょうか?
モジュールをつかってcwd()で取得できるようなのですが、モジュールが入っていないサーバでも動くようにしたいのですがうまくできません・・・
どなたかご存知でしたら教えてください。

Aベストアンサー

if($^O eq "MSWin32"){
$cwd=`cd`;
} else {
$cwd=`pwd`;
}
print $cwd;
--------------
ぐらいでいいんじゃないでしょうか


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

人気Q&Aランキング