こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

回答受付中の質問

番号のある行とその一つ下の行を抜き出していく

次のようなテキストファイルがあります。
(hogehoge の部分はそれぞれの行によって全く異なる文章です)

253 hogehoge
hogehoge
(間に数百行あり)
101 hogehoge
hogehoge
(間に数行あり)
100 hogehoge
hogehoge
(間に数行あり)
99 hogehoge
hogehoge
(間に数百行あり)
14 hogehoge
hogehoge
(間に数行あり)
13 hogehoge
hogehoge

これから、
253 の数字がある部分でいえば
253 hogehoge
の行とそのすぐ下の1行の2行ずつを
抜き出して
全てつなぎ合わせたテキストファイルを作りたいです。
どのようにすればよいでしょうか?
また、2桁の数字の行が
013 hogehoge
などとなっていた時は、同じことをやるのに
どのようにやり方を変えればいいでしょうか?
(これができれば
 004 hogehoge
 などの行まであっても同じやり方でできると思います。)
よろしくお願いします。

投稿日時 - 2017-08-30 20:41:13

QNo.9368968

困ってます

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(6)

ANo.6

不規則な内容のファイルを扱う
数字スペース文字列の規則を目印にする
続いて出現する文字列と2行を抜き出す
検索数字は連番で良い
検索数字は000の3桁文字でフォーマット
検索ファイル内容で不具合あるかもしれない
$ perl nukidashi.pl リスト.txt


use strict;
#use warnings;

my $end = 255; ### 検索開始数字(大きい数字から)

my $start = 4; ### 検索終了数字(小さい数字まで)

sub memo_1{
my @ken = @_;

my $kai_1 = 0; ### 1行目を改行するなら1

my $kai_2 = 0; ### 2行目を改行するなら1

my $count_1 = 0;
my $Log;

open my $HK ,"$ARGV[0]" or die;
my @gen = <$HK>; close $HK;

for my $kan(@ken){
for(@gen){
next if $_ =~ m[\s+\n|^\n];
my $scalar_1 = [split(' '),$_];
if($kan and $scalar_1->[0] eq $kan){
$kai_1 ? $Log .= "$_" : chomp($Log .= "$_");
$count_1++;
next; }

if($count_1){
$kai_2 ? $Log .= "$_" : chomp($Log .= "$_");
$count_1 = 0;
last; }
}}
$Log;
}

my @haire;
my $count = 0;
$start--;

for(;$start < $end;$start++){
my $min = $end - $count;
$haire[$count] = sprintf("%03d",$min);
$count++; }

print memo_1(@haire),"\n";

### 手入力用
# my $jo_1 = join('\',\'',@haire);
# print"$jo_1\n";
###

投稿日時 - 2017-09-04 17:07:27

お礼

ありがとうございます。
たびたびお時間を割いて作っていただきまして
とてもありがたいのですが、
今回は
行番号(とその次の行)の直後が日本語から始まっていると
その行番号の部分は結果に出てこなくなります。
行番号ごとに改行もなされないようですが、
あまり作り直していただくのも気の毒ですので。

投稿日時 - 2017-09-06 12:15:01

ANo.5

とりあえず動かすで勘弁して下さい
デバックし出したら終わらないので

#use warnings;

2行目を上記にして下さい
比較対象が無いよエラーは消えます

投稿日時 - 2017-09-02 21:11:44

お礼

> 番号が振ってある行全てから2行ずつ抜き出したいです。
結局
$ for i in {253..013} ; do echo -n $i',' ; done
この実行結果でできたやつをスクリプトに貼り付けました。
my @key=('253','013','004'); ###抜き出したい番号
この形式にするなら
$ for i in {253..004} ; do echo -n "'"$i"'"',' ; done
ですね。
途中で抜けている番号については
その番号とそのすぐ下の行(空白行でもOKでした)を手作業で入力ファイルに入れるということをやりました。
そうしないと処理がそこの番号までで止まりますので。
それぞれの行番号の所で改行されるとなお良かったのですけど、
おかげさまで何とか目的にたどりつきました。
ありがとうございました!

投稿日時 - 2017-09-03 09:09:23

ANo.4

$ perl nukidashi.pl リスト.txtで行きましょう
@keyに番号をシングルクォートで挟んでコロンで区切る

use strict;
use warnings;

sub memo_1{
my @ken = @_;
my $kai_1 = 0; ### 2行目を改行するなら1
my $count_1 = 0;
my $count_2 = 0;
my $Log;

open HK ,"$ARGV[0]" or die;

while(<HK>){
my $scalar = [split(' ',$_)];
if($ken[$count_1] and $scalar->[0] eq $ken[$count_1]){
chomp($Log .= "$_");
$count_2++;
next; }

if($count_2 > $count_1){
$kai_1 ? $Log .= "$_" : chomp($Log .= "$_");
$count_1++; }
}
close HK;
$Log;
}

my @key=('253','013','004'); ###抜き出したい番号
print memo_1(@key),"\n";

投稿日時 - 2017-09-02 15:49:17

お礼

たびたびありがとうございます。
まず、最初から書いておかなければならなかったと思いますが
(申し訳ありません)
リスト.txt には
251,250
のように途中で抜けている番号もあります。
空白行もたくさんあります。
この回答のスクリプトにおいて

my @key=('253','252','249','13'); ###抜き出したい番号

というようにすれば、実行した時に

Use of uninitialized value in string eq at nukidashi.pl line 15, <HK> line 69.

こういうメッセージが10個くらい出てきますが
ここで明示的に指定した番号の行(とそのすぐ下の行)は抜き出されます。
全て手作業で番号をここに書かなければいけないでしょうか?

投稿日時 - 2017-09-02 20:38:32

ANo.3

No.1です すいません訂正
頭が0ならシングルクォートして下さい

sub memo_1{
my @ken = @_;

my @ken = @_;
my $count_1 = 0;
my $count_2 = 0;
my $Log;

open my $hai ,'hoge.txt';

while(<$hai>){
my $scalar = [split(' ',$_)];
if($scalar->[0] eq $ken[$count_1]){
$Log .= "$_";
$count_2++;
next; }

if($count_2 > $count_1){#print"End $_\n";
$Log .= "$_";
$count_1++; }
}
$Log;
}
close $hai;

print memo_1(253,'013','004'),"\n";

投稿日時 - 2017-09-02 12:44:57

お礼

たびたびありがとうございます。
> 私としては
> pythonでもperlでもawkでも
> どれでも大丈夫です。
すみません、書き方が悪かったのかもしれませんけど
私はこういった言語のどれに対してもほとんど知識がありません。
自分でも少し調べて読み解こうとしてみようとは思いますが、自信はありません。

この回答のスクリプトの
print memo_1(253,'013','004'),"\n";
この行のみを
print memo_1(253,13),"\n";
こう変えて実行しました。

$ perl nukidashi.pl
253長い日
オプション
13始め
カヤック

こういう結果です。
番号が振ってある行全てから2行ずつ抜き出したいです。
> my @hai <= サンプルなので削除してください
ここをいじろうと思っても
どういう風にいじれば適切か分かりませんし。

投稿日時 - 2017-09-02 14:17:17

ANo.2

No.1です

my @hai <= サンプルなので削除してください

読み込むファイルをopenして
ループに取り込んでください

そして検索数字をmemo_1()に送る

投稿日時 - 2017-09-02 11:53:18

ANo.1

すんません、Python知りません
Perlなんで書き換えてください

sub memo_1{
my @ken = @_;

my @hai = ( # 検索文字列
'99 AAA88A','88 BBB77B',
'77 CCC66C','66 DDD55D',
'55 EEE44E','44 FFF33F',
'33 GGG22G','22 HHH11H',
'11 MMM00M','00 NNN99N');

my $count_1 = 0;
my $count_2 = 0;
my $Log;

for(@hai){
if($ken[$count_1] and $_ =~ m[^$ken[$count_1]]){
$Log .= "$_, ";
$count_2++;
next; }

if($count_2 > $count_1){
$Log .= "$_, ";
$count_1++;
next; }
}
$Log;
}

print memo_1(88,55,22),"\n";

投稿日時 - 2017-09-02 01:24:57

お礼

ありがとうございます。
なぜかこの質問はpythonのコーナーが指定されています。
私としては
pythonでもperlでもawkでも
どれでも大丈夫です。

回答くださったperlスクリプトを nukidashi.pl という名前で保存して
リスト.txt という入力ファイルに作用させてみたのですけど
$ perl nukidashi.pl リスト.txt
88 BBB77B, 77 CCC66C, 55 EEE44E, 44 FFF33F, 22 HHH11H, 11 MMM00M,
こういう実行結果になります。
どこがマズイのでしょうか?

投稿日時 - 2017-09-02 10:25:15

あなたにオススメの質問