2016-10-07 12 views
1

値のグループを抽出しようとします。この場合、私のLinuxシステムの設定ファイルにallowed_hostsに属するすべてのipsが抽出されます。PERLは設定ファイルから値を抽出します

configApp.cfg 
bla bla bla 
    ... 
allowed_hosts = 10.121.120.163,10.121.120.164, ips, ips, more ips ... 
    ... 
something . 

私はすでに、Webページhttp://perlmaven.com/how-to-extract-strings-from-a-file

を読んで、私は私のスクリップでいくつかの問題を持っている: はので、私はこれを持っています。

open(my $file, '<:encoding(UTF-8)', $config_file) 
    or die "Could not open file '$config_file' $!"; 
while (my $row = <$file>) { 
chomp $row; 
my @strings = $row =~ /[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}/g; 
foreach my $s (@strings){ 
    print "'$s'"; 
} 
} 

私は正規表現の表現を助けることができます。ありがとう

+0

HTTP ://www.regexe.com/ 私はいつも私の正規表現をテストするためにこのサイトを使用しています! –

+0

@JReidまた、https://regex101.com/ – PerlDuck

+0

を試してください。中括弧をエスケープする必要はありません。中カッコを使用するときはエスケープする必要はありません(リテラル中括弧を使用する場合にのみエスケープする必要があります。 perl 5では無用ですが、perl 6では必須となります)、正規表現のPerl構文はBRE構文(基本正規表現)とは異なります。 –

答えて

0

は、特定の問題

use warnings 'all'; 
use strict; 
use feature 'say'; 

my $file = 'configApp.cfg'; 

open my $fh, '<', $file or die "Can't open $file: $!"; 

my @allowed_hosts; 

while (<$fh>) 
{ 
    if (/^allowed_hosts\s*=\s*(.*)/) 
    { 
     my @hosts = split /\s*,\s*/, $1; 
     push @allowed_hosts, \@hosts; 
    } 
} 

# Process hosts as needed 
say "@$_" for @allowed_hosts; 

コメント

  • プロセスキャプチャパターンを使用し/^allowed_hosts/

  • を必要としている線のみ与えられ、それを行うための別の方法です、入手可能:$1

  • ストア確か一つだけ/^allowed_hosts/ラインがある場合は、すべての結果

  • とアレイ上の参照としてラインの結果と配列は、直接splitから別の配列–店のリターンのための必要はありませんループの外側で宣言された@allowed_hostsに挿入します。この行が解析されたら、ループを終了することもできます。複数の行(またはファイル)で

、我々はまた、

if (/^allowed_hosts\s*=\s*(.*)/) 
{ 
    push @allowed_hosts, [ split /\s*,\s*/, $1 ]; 
} 

無名配列を使用することができ、我々はそれを離れて隠し前にしかし、その後、私たちは、あなたはしばらくの間、仲介@hostsで、結果を確認することはできません必要に応じてチェックや追加の検証、選択や処理を追加できます。あなたは、これは、最後の行は、より読みやすいでしょうリストはビットコンマのではなく、その後にスペースを分離した

 
10.121.120.163 10.121.120.164 ips ips more ips ... 
2

断片化問題を扱うことはしばしば簡単です。 IPアドレスを探すことは難しい問題です(誰かがそこにIPv6アドレスを入れるまで待つだけです)。そのファイルには許可されていない他のIPアドレスが含まれているかもしれません。 abnormal_hosts = 123.234.56.78をお持ちの場合はどうなりますか?

代わりにallowed_hosts = somethingを探します。これはずっと簡単で安全です。

  1. key = valueをキーと値に分割します。
  2. 「キー」が「allowed_keys」であることを確認します。
  3. その場合は、値をIPに分割します。

use strict; 
use warnings; 
use v5.10; 

# Simulate the contents of a file. 
my @Lines = (
"configApp.cfg\n", 
"bla bla bla\n", 
"\n", 
"dangerous_hosts = 24.45.62.1\n", 
"allowed_hosts = 10.121.120.163, 10.121.120.164 ,127.0.0.1,8.8.8.8\n", 
" something .\n" 
); 

# Don't use a foreach loop to read a file, it wastes memory. 
# This is for testing only. 
for my $line (@Lines) { 
    chomp $line; 

    # Split the line into the key and value. 
    # If it isn't a key = val line there will be no key. 
    my($key, $val) = split /\s*=\s*/, $line; 

    # If the key isn't there, or if it isn't "allowed_hosts", skip this line. 
    next if !defined $key or $key ne 'allowed_hosts'; 

    # Now split the IP list. Be sure to account for whitespace. 
    my @ips = split /\s*,\s*/, $val; 

    say "Allowed Hosts: @ips"; 

    # We found the line, no need to read the rest of the file. 
    last; 
} 

注IPアドレスを解析する必要はありません。すべてのプログラムは、それがコンマ区切りのリストであることを気にしています。もしあなたが@ipsの内容を確かめることができれば、行の他のすべてを解析することなく一度に1つずつ行うことができます。

また、私は常に=,のようなものの周りの可能な空白を考慮に入れています。人々は本当にスペースを置く場所について一貫していない。

-1

2つのステップで行います。まず、あなたはこれを試すことができることをしたくない場合は

if($row =~ /^\s*allowed_hosts\s*=\s*(.*)/) { 
    foreach my $s (split(/\s*,\s*/,$1)) { 
    print("allowed: $s\n"); 
    } 
} 

個々のエントリを取得するには、分割を使用し、IPアドレス/ホスト名のリストを抽出します。

while(my $row = <$file>) { 
    chomp; 
    print("'$_'\n") foreach (split(/\s*,\s*/,($row =~ /^\s*allowed_hosts\s*=\s*(.*)/i)[0])); 
} 
2

あなたのようにそれを行うことができます

open(my $fh, '<', $config_file) 
    or die "Could not open file '$config_file': $!"; 

while(<$fh>) { 
    next until /^allowed_hosts = /; 
    my @ips = /\d+[^\s,]+/g; 
    print join "\n", @ips; 
    last; 
} 

next untilは、良いものが見つかるまですぐにすべての行を破棄します。
すべての一致は@ips変数に格納されます。
あなたは既にこの行にipsが含まれていることを知っているので、IPを記述するために明示的なパターンを作る必要はなく、空白とカンマを避ける必要があることに注意してください。
lastはループを停止します。
ファイルを開くためにエンコーディング情報を追加する必要はありません。おそらく、多くの設定ファイルと同じようにASCII文字で書かれている可能性がありますが、間違っている可能性があります。

結果をループ外で使用できるようにするには、@ips変数をループ外(その前)に宣言する必要があります。ここで

+1

シンプルで素晴らしい。提案:入力に複数の 'allowed_hosts'行が含まれている場合、' my @ips =/\ d + [^ \ s、] +/g; 'を' push @ips、/ \ d + [^ \ s 、] +/g; '最後の行を削除します。しかし、あなたのパターンは素晴らしいです。 :-) – PerlDuck

+2

'/^allowed_hosts = /'は 'allowed_hosts ='やその他のスペースでは動作しません。人間はスペーシングに関して非常に矛盾しているので、手書きの書式の場合、 '\ s *'を使用します。 – Schwern

+1

@Schwern:あなたの発言は正しいですが、私は質問に記載された情報に固執することを好む。著者は自由にコードを変更して(少しの費用で)より柔軟にすることができます。 –

0
use strict; 
use warnings; 

use Config::Simple; # you may have to install this one 

my $cfg = Config::Simple->new(configApp.cfg); 

my @hosts = split " ", $cfg->param('allowed_hosts'); 

印刷し掲載正確なテキスト付き

のような:

​​
関連する問題