Perl:ファイルの各行からn番目とm番目の区切られた単語を取得する

StackOverflow https://stackoverflow.com/questions/156009

  •  03-07-2019
  •  | 
  •  

質問

Nagiosで監視するホストを追加する面倒な方法のため(IPとホスト名のみを必要とする以前のプログラムとは対照的に、ホストオブジェクトを定義する必要があります)、これを自動化するのが最善であると考えました、Perlを学ぶのに最適な時期です。現時点で私が知っているのはC / C ++とJavaだけだからです。

読み取り元のファイルは次のようになります。

xxx.xxx.xxx.xxx hostname #comments. i.dont. care. about

必要なのは、最初の2つのキャラクターの束だけです。これらは明らかにスペースで区切られていますが、一般性のために、何でもかまいません。より一般的にするために、なぜ1番目と3番目、または4番目と10番目ではありませんか?確かに何らかの正規表現アクションが関係しているに違いありませんが、念のために、このタグは今のところオフのままにします。

役に立ちましたか?

解決

結果を処理するためのPerlをこれ以上書かないのであれば、ワンライナーは素晴らしいです。

しかし、より一般的には、より大きなPerlプログラムのコンテキストでは、次のようなカスタムの正規表現を作成します。

if($line =~ m/(\S+)\s+(\S+)/) {
     $ip = $1;
     $hostname = $2;
}

...または split 演算子を使用します。

my @arr = split(/ /, $line);
$ip = $arr[0];
$hostname = $arr[1];

どちらの方法でも、無効な入力をチェックするロジックを追加します。

他のヒント

これをコードゴルフに変えましょう!デビッドの優れた答えに基づいて、ここに私のものがあります:

perl -ane 'print "@F[0,1]\n";'

編集:実際のゴルフの提出は、次のようになります(5回のストロークを削る):

perl -ape '$_="@F[0,1]
"'

しかし、それはこの質問の目的には読みにくいです。 :-P

一般的な解決策は次のとおりです(コードゴルフから少し離れた場合)。

#!/usr/bin/perl -n
chop;                     # strip newline (in case next line doesn't strip it)
s/#.*//;                  # strip comments
next unless /\S/;         # don't process line if it has nothing (left)
@fields = (split)[0,1];   # split line, and get wanted fields
print join(' ', @fields), "\n";

通常splitは空白で分割されます。それが望んでいない場合(たとえば、解析/etc/passwd)、区切り文字を正規表現として渡すことができます:

@fields = (split /:/)[0,2,4..6];

もちろん、コロンで区切られたファイルを解析している場合、そのようなファイルにコメントがなく、削除する必要もない可能性もあります。

シンプルなワンライナーは

perl -nae 'print "$F[0] $F[1]\n";'

-F

で区切り文字を変更できます

David Nehme氏:

perl -nae 'print "$F[0] $F[1}\n";
-aスイッチを使用する

。私はそれを調べなければなりませんでした:

-a   turns on autosplit mode when used with a -n or -p.  An implicit split
     command to the @F array is done as the first thing inside the implicit
     while loop produced by the -n or -p.

毎日何かを学びます。 -nを指定すると、各行が渡されます

LINE:
    while (<>) {
        ...             # your program goes here
    }

そして最後に-eは、プログラムの1行を直接入力する方法です。 perlrun(1)以上にすることができます。このほとんどは<=>マンページのリッピングでした。

rayが尋ねたので、Perlの暗黙性を使用せずにプログラム全体を書き換えたいと思いました(<ARGV>の使用を除く。これは手で書くのは難しいです)。これは恐らくPythonの人々をより幸せにするでしょう(:-Pにもかかわらず中括弧):

while (my $line = <ARGV>) {
    chop $line;
    $line =~ s/#.*//;
    next unless $line =~ /\S/;
    @fields = (split ' ', $line)[0,1];
    print join(' ', @fields), "\n";
}

見逃したものはありますか?うまくいけない。 ARGVファイルハンドルは特別です。コマンドラインで指定された各ファイルは、何も指定されていない限り読み込まれます。指定されていない場合は、標準入力を読み込みます。

編集:ああ、忘れた。 split ' 'とは異なり、split / /も魔法です。後者はスペースに一致します。前者は、任意の量の空白に一致します。 splitにパターンが指定されていない場合、この魔法の動作がデフォルトで使用されます。 (しかし/\s+/ はどうでしょうか?' 'と<=>は似ていますが、行頭の空白がどのように扱われるかを除いて。<=>は本当に魔法です。 )

物語の教訓は、多くの魔法の振る舞いが好きなら、Perlは素晴らしいことです。バーがない場合は、Pythonを使用してください。 :-P

行番号LのN番目からM番目の文字を検索するには---ラベル検索の例


@echo off

REM Next line = Set command value to a file  OR  Just Choose Your File By Skipping The Line
vol E: > %temp%\justtmp.txt
REM  Vol E:  = Find Volume Lable Of Drive E

REM  Next Line to choose line line no. +0 = line no. 1 
for /f "usebackq delims=" %%a in (`more +0 %temp%\justtmp.txt`) DO (set findstringline=%%a& goto :nextstep)

:nextstep

REM  Next line to read nth to mth Character  here 22th Character to 40th Character
set result=%findstringline:~22,40%

echo %result%
pause
exit /b

find label.cmdとして保存

結果はドライブEラベルになります

楽しむ

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top