以下のようなファイルを入力して、配列/連想配列に格納、これを後段の処理に利用したいと考えています。結構複雑なことをやってようやく処理できたのですが、もっと良い方法はありませんでしょうか。
逆に入力ファイルのフォーマットを処理しやすいものにしてしまっても構いません(perl形式で記述してrequireする方法はここではNGとします)。アイディア宜しくお願い致します。
1. #はコメント
2. 最終イメージ
Vegetable: Tomato, Lettuce, Potato
Fish : Salmon, Tuna,
Fruit : Banana, Orange
※ ####~次の####までを塊として処理する部分で、ちょっと冗長な気がしています
--- >8 --- >8 --- >8 --- >8 --- >8
# This is comment line
# File created by ...
# since 5/May/2009
#### Vegetable
Tomato
Lettuce
Potato
# Carrot <-- Comment line
#### Fish
Salmon
Tuna
#### Fruit
Banana
Orange
--- >8 --- >8 --- >8 --- >8 --- >8
<<スクリプト例>>
# ここでは@keyにカテゴリ(Vegetable, Fish, Fruit)、@valueに各々の食品名(Tomato, lettuce,...)を入れています
#! /usr/bin/perl
my $flag_first_match = 1;
my $flag_hit = 0;
my @key;
my @value;
open (LIST, "aaa.txt") || die "open error";
while(<LIST>){
if($flag_hit == 1){
$flag_hit = 0;
$flag_seek = 1;
if($flag_first_match==1){
$flag_first_match = 0;
}
}
if(m/####\s+(.*)$/){
$key_tmp = $1;
$flag_hit = 1;
$flag_seek = 0;
}
chomp();
if(m/^\s*$/){next;} if(m/^#\s+/){next; }
if($flag_hit==1 && $flag_first_match ==0 ){ # for on-going loop
push(@value, $ref_tmp);
}
if($flag_hit == 1){ # for next loop
push(@key, $key_tmp);
$ref_tmp = [];
}
if($flag_seek == 1){
push(@$ref_tmp, $_);
}
}
close(LIST);
### 印字確認
{
local $, = ", ";
for($i=0; $i < @key; $i++){
printf ("%2d | %-35s: ", $i, $key[$i]);
foreach $ref ($value[$i]) {
for ($j=0; $j < @$ref; $j++){
print "$j= @$ref[$j] ";
}
}
print "\n";
}
}
<<出力>>
0 | Vegetable : 0= Tomato 1= Lettuce 2= Potato
1 | Fish : 0= Salmon 1= Tuna
2 | Fruit :
No.1ベストアンサー
- 回答日時:
> 逆に入力ファイルのフォーマットを処理しやすいものにしてしまっても構いません
じゃあ
1. #以降はコメント
2. -以降はカテゴリ
と割り切ってしまうのはどうでしょう?
#以降は何がなんでもコメントで、カテゴリは別の文字(私の場合は-にしました)にしたほうが考えやすいと思います。
####をコメントに使うとなると、
「先頭に#があった場合はコメントだが、####だった場合は例外」
としなければなりません。
例外はできれば増やしたくないものです。
私のフォーマットに変えたファイルの内容は以下です。
------------------------
# This is comment line
# File created by ...
# since 5/May/2009
- Vegetable
Tomato
Lettuce
Potato
# Carrot <-- Comment line
- Fish
Salmon
Tuna
- Fruit
Banana
Orange
------------------------
プログラムの内容は以下。
------------------------
#! /usr/bin/perl
use warnings;
use strict;
my $category;
my %pair;
open (LIST, "aaa.txt") || die "open error";
while(<DATA>) {
chomp;
next if /^\s*$/; # blank line
next if /^#/; # comment line
if (/^-\s*(\S+)/) {
$category = $1;
} else {
if (defined $category) {
s/^\s*(.*?)\s*$/$1/; # 前後の空白を取り除く
push @{$pair{$category}}, $_;
}
}
}
close(LIST);
### 印字確認
my @keys = sort keys %pair;
for (my $i = 0; $i < @keys; $i++) {
my $key = $keys[$i];
print "$i | $key : " . join(", ", @{$pair{$key}}) . "\n";
}
------------------------
出力結果は以下です。
------------------------
0 | Fish : Salmon, Tuna
1 | Fruit : Banana, Orange
2 | Vegetable : Tomato, Lettuce, Potato
------------------------
ただこのプログラムの問題は、見ての通りカテゴリのアルファベット順になってしまうことです。
元のファイルに書かれた順番通りにしなければならないのなら
プログラムを変更しなければなりません。
有難うございます。
アルファベット順であることは特に構いません。
僕が愚かで、最初のキーを「見つけるまで」などを
my $flag_first_match = 1;
my $flag_hit = 0;
$flag_seek などとしていたのですが、definedを使えばすっきり処理できる($flagもいらない)ことは大変参考になりました。
my $category;
...
if (/^-\s*(\S+)/) {
$category = $1;
} else {
if (defined $category) {
...
どうも有難うございます。
No.2
- 回答日時:
YAMLモジュールとリファレンスを使ってよければ。
./file/data.txt
================================================
# File created by...
# since 5/May/2009
- category : Vegetable
data :
- Tomato
- Lettuce
- Potato
# Carrot
- category : Fish
data :
- Salmon
- Tuna
- category : Fruit
data :
- Banana
- Orange
================================================
↑行頭の半角スペースが認識してくれないので代わりに全角スペースをいれました。行頭の全角スペースを半角スペースに直して使っていただきたいです。
./test.pl
================================================
use strict;
use warnings;
use YAML();
my $data = YAML::LoadFile("./file/data.txt");
for(my $i=0; $i<@{$data}; $i++){
my $str = "";
for(my $ii=0; $ii<@{$data->[$i]{data}}; $ii++){
$str .= $ii. "=". $data->[$i]{data}[$ii]. " ";
}
print "$i | $data->[$i]{category} : $str\n";
}
================================================
<<出力>>
0 | Vegetable : 0=Tomato 1=Lettuce 2=Potato
1 | Fish : 0=Salmon 1=Tuna
2 | Fruit : 0=Banana 1=Orange
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Visual Basic(VBA) excel VBA if文について 3 2022/03/27 17:42
- Visual Basic(VBA) ExcelVBAでDo Until loopのネスト、IF文を使って一致する物と一致しない物としたい 11 2022/12/24 17:46
- その他(プログラミング・Web制作) pythonのDjangoでHTML内で変数を利用したいです 3 2022/05/15 15:33
- Visual Basic(VBA) マクロVBA 1シートをまとめる 閉じ方 初心者 SOS! 1 2022/06/17 14:54
- PHP PHPでCSVを出力するさいに、ループの中で前の行の値を変更したい 3 2022/10/27 17:44
- JavaScript フォームが空欄の時にフォームの外をクリックすると、エラーが出るコードを調べています。 1 2023/06/25 11:51
- Perl perl このテキストファイルを簡単に配列に入れるには? 2 2022/04/27 20:24
- JavaScript javascript作成してます。ラジオボタンで判定するコードを書いてます。 1 2023/07/18 11:03
- CGI perlで書いたcgiでsqliteの使い方を教えてください 2 2023/05/08 21:29
- Visual Basic(VBA) ExcelVBAで、index、match関数を使用して、指定範囲に出力したい 3 2022/10/18 21:53
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
perlのプログラミング 部分入れ...
-
Strawberry Perl for Windows ...
-
アルファベットに付いて質問し...
-
Perlで同じフォルダにある任意...
-
perlでリテラル値はメモリにど...
-
ペプシコーラとコカ・コーラとD...
-
perlをバージョンアップしたら...
-
openした後、closeしないでプロ...
-
#!/usr/bin/perlで書きだしたCG...
-
Perlのエラーについてご教授く...
-
perlのflock関数でロックをかけ...
-
AI sisterとは、偽物の人ですか?
-
perlで2次元配列をサブルーチ...
-
perlのrequireの動き方について...
-
perlについての質問
-
Blenderについて
-
Perl の外部モジュールの利用方法
-
perl このテキストファイルを簡...
-
Perlでファイルの末尾から指定...
-
秀丸での一括変換について
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
テキストファイルで提出とは?
-
openした後、closeしないでプロ...
-
perlをバージョンアップしたら...
-
INDIRECT 横に再度抽出したい
-
Perl の外部モジュールの利用方法
-
Perlで特定文字列から特定文字...
-
Perlのエラーについてご教授く...
-
bashスクリプト
-
Strawberry Perl for Windows ...
-
perlで2次元配列をサブルーチ...
-
TeraPadエディターの操作方法に...
-
アルファベットに付いて質問し...
-
perlのflock関数でロックをかけ...
-
ファイルアイコンの左下に緑の□...
-
perlプログラミング 空白行削除
-
Wallpaper Engineでおすすめの...
-
Perlで時間の計算
-
perlのrequireの動き方について...
-
perlでリテラル値はメモリにど...
-
画像が表示でnull; this.src
おすすめ情報