電子書籍の厳選無料作品が豊富!

~log.txt~
abc def ghi ddd zzz
123 abc 456 ddd 789 000
abcd abc abc/ef ddd
aaa ddd bbb abc

~search.pl~
$FILE = 'log.txt';
$Search = "abc";
open(FILE, "<$FILE") or die("error :$!");
eval{ flock(FILE, 1) };
@DATA = <FILE>;
close FILE;
my @Search = grep(/$Search/, @DATA);
while (<@Search>) {$a++}
print @Search;
<STDIN>

このソースですと、「abc」を検索するのに、
行で検索して、結果全て返ってきます。

これを、(列[0][1][2][[3][4])で振分
[1]の部分の「abc」のみを返したい
結果・・・
123 abc 456 ddd 789 000
abcd abc abc/ef ddd

としたいのですが、どうすればいいのでしょうか・・・?

質問者からの補足コメント

  • 後数字が入ると反応しないみたいです・・・

    No.1の回答に寄せられた補足コメントです。 補足日時:2017/03/13 15:40

A 回答 (5件)

>$Search = "zzz";


>最後方[5]の場合
>$Search = "zzz\n";
>にしないと返ってこないのですが、これは仕様ですか?
はい、仕様です。そのような場合、事前に$_の改行(\n)を削除しておきます。
但し、$_が改行がなくなっているので、印字する場合は、改行をつけて印字します。

>部分一致です!
部分一致の場合は、比較方法が正規表現での比較になります。

今回の例では、いかのようになります。
$FILE = 'log.txt';
$Search = "b"; #①
open(FILE, "<$FILE") or die("error :$!");
eval{ flock(FILE, 1) };
while(<FILE>){
chomp($_); #②
@elm = split(/,/,$_);
if ($elm[1] =~ /$Search/){ #③
print $_,"\n"; #④
}
}
close FILE;
<STDIN>

②:改行の削除
③:正規表現で、bの部分一致検索
④:一致時、改行を付けて印字
    • good
    • 0
この回答へのお礼

ありがとうございます!

仕様なら少し安心しました!

やりたいことができました!
色々教えていただき本当にありがとうございます!

お礼日時:2017/03/14 09:40

No3です。


>>いえ、$elm[1] を $elm[5]を変えればOKです。
>これは、すみません・・私のテキストが「カンマ区切り」も試していたときにおきて
>いました。空白区切りでだと、[5]は返ってきました。
>空白区切りは「\s+」でカンマ区切りは「,」だけでは不十分なのでしょうか?

空白区切りとカンマ区切りは、全く別物です。
カンマ区切りなら、
@elm = split(/\s+/,$_); を
@elm = split(/,/,$_); にします。


>>$Search = "abc"; を
>$Search = "b"; に変えてください。
>「b」に変えたのですが、完全一致でないと、返してくれなかったです;;

質問が完全一致と思って回答したのですが、そうではないようですね。
前方一致、後方一致、部分一致が考えられますが、どのケースを想定していますか?
前方一致:先頭の1文字がbであれば、以降はなんでも良い
後方一致:最後の1文字がbであれば、以前はなんでも良い
部分一致:文字列中に1文字bがあればそれで良い
    • good
    • 0
この回答へのお礼

>空白区切りとカンマ区切りは、全く別物です。
ありがとうございます!
ただ、カンマ区切りの場合ですと、
$Search = "zzz";
最後方[5]の場合
$Search = "zzz\n";
にしないと返ってこないのですが、これは仕様ですか?

>前方一致、後方一致、部分一致が考えられますが、どのケースを想定していますか?
すみません;;私の説明不足で・・・

部分一致です!

お礼日時:2017/03/13 16:48

No1です。


>これに、
>1文字でも検索できて「abc」を検索としましたが、「b」でも同じ答えが返ってくるようにと、
$Search = "abc"; を
$Search = "b"; に変えてください。

>最後の列[5]が反応していないのですが、これも反応させたいのですが、
>$elm[1] を $elm[5]
>に変えるだけではダメなのでしょうか・・??
いえ、$elm[1] を $elm[5]を変えればOKです。

>後数字が入ると反応しないみたいです・・・
すみません、意味がよくわかりません。例をあげて、具体的に説明していただけますでしょうか。
    • good
    • 0
この回答へのお礼

>$Search = "abc"; を
$Search = "b"; に変えてください。

「b」に変えたのですが、完全一致でないと、返してくれなかったです;;

>いえ、$elm[1] を $elm[5]を変えればOKです。
これは、すみません・・私のテキストが「カンマ区切り」も試していたときにおきて
いました。空白区切りでだと、[5]は返ってきました。
空白区切りは「\s+」でカンマ区切りは「,」だけでは不十分なのでしょうか?

>すみません、意味がよくわかりません。例をあげて、具体的に説明していただけますでしょうか。

すみません;;これもカンマ区切りで試しているときのでした。

まだ、理解が不十分なのですが、
カンマ区切りと空白区切りは別物なのでしょうか・・・?

お礼日時:2017/03/13 16:27

方法1:


一度 @Search に入れたあと、各要素について、該当箇所が「abc」のものだけのリストを作る
my @Search2=() ;
foreach my $s (@Search) {
if (該当箇所が「abc」) {
push @Search2, $s ;
}
}

方法1':
grepを使わず、最初から該当行だけ取り出す
foreach my $s (@Data) {
if (該当箇所が「abc」) {
push @Search, $s ;
}
}

方法2:
「列[0][1][2][[3][4]で[1]の部分の「abc」のみにマッチする」という正規表現になるように工夫する。

方法3
http://perldoc.jp/func/grep
に「特に、正規表現の使用に制限されません。」とあるように、
grep BLOCK LIST ;
という構文では、BLOCK部分にかなり自由にプログラムを書けます。例えば

my @Search = grep
{
my @s = split(/\s+/) ; #空白で分割する
($s[1] eq $Search) ; #分割された1番目が、$Searchと同じかどうか。 最後に評価された式の値が、grepの判定に使われる
} @DATA ;
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます

とりあえず方法1を試めさせていただくのに
「該当の箇所」のものだけのリストとは
別にテキストファイルを作るということですか・・?

お礼日時:2017/03/13 15:43

以下のようにしてください。


-------------------------------
$FILE = 'log.txt';
$Search = "abc";
open(FILE, "<$FILE") or die("error :$!");
eval{ flock(FILE, 1) };
while(<FILE>){
@elm = split(/\s+/,$_);
if ($elm[1] eq $Search){
print $_;
}
}
close FILE;
<STDIN>
----------------
この回答への補足あり
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます

実行確認できました。

すみません。
これに、
1文字でも検索できて「abc」を検索としましたが、「b」でも同じ答えが返ってくるようにと、

最後の列[5]が反応していないのですが、これも反応させたいのですが、
$elm[1] を $elm[5]
に変えるだけではダメなのでしょうか・・??

お礼日時:2017/03/13 15:38

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