LINUX.ORG.RU
ФорумAdmin

perl system()

 , ,


0

1
system ("nbtscan -f ip.list | sed '1,4D'| sed "s/\( \)\+/\t/g" | cut -f '1 2 5' > temp.list");

Не могу заставить работать в perl. Не вносит в файл выделенные столбцы, вносит в файл весь вывод. Что не так. 

Из перла вызывать sed и cut - это какой-то особый способ мастурбации. Что мешает дёрнуть nbtscan (кстати, что это?) и самим перлом его обработать? И отлаживать легче будет.

DELIRIUM ☆☆☆☆☆
()
Ответ на: комментарий от madcore

sed 's/\( \)\+/\t/g' там вывод пробелами, вот этим я меняю пробелы на табуляцию.

tooncheg
() автор топика

Хинт: в перле кроме system есть и другие функции, в том числе s/// имеется.

anonymous
()
Ответ на: комментарий от DELIRIUM

This is a command-line tool that scans for open NETBIOS nameservers

tooncheg
() автор топика

system(..|sed ..|sed..|cut..>>)
perl

Месье знает толк

Kronick
()

Я понятия не имею, что такое nbtscan. Нагуглил его выхлоп и положил в файлик:

$ cat nbtscan.txt 
       NetBIOS Remote Machine Name Table

   Name               Type         Status
---------------------------------------------
XPDEV          <00>  UNIQUE      Registered
UNIXWIX        <00>  GROUP       Registered
XPDEV          <03>  UNIQUE      Registered
XPDEV          <20>  UNIQUE      Registered
UNIXWIX        <1E>  GROUP       Registered

$ cat nbtscan.txt | sed '1,4d' | sed -E 's/( )+/	/g' | cut -f '1 2 5' 
XPDEV	<00>
UNIXWIX	<00>
XPDEV	<03>
XPDEV	<20>
UNIXWIX	<1E>

Поскольку пятого столбца в выхлопе нет, в cut -f достаточно передать '1 2'

И вообще скрипт можно упростить:

$ cat nbtscan.txt | awk 'NR>4{ print $1 "\t" $2 }'
XPDEV	<00>
UNIXWIX	<00>
XPDEV	<03>
XPDEV	<20>
UNIXWIX	<1E>

Теперь разберёмся с сохранением в файл из Перла:

system q(cat nbtscan.txt | awk 'NR>4{ print $1 "\t" $2 }' > temp.list);

evbogdanov
()
Ответ на: комментарий от evbogdanov

Спасибо. А можно сделать в однострочном режиме, так что в зависимости от результата (есть вывод в консоль или нет) выполнения perl file.pl выполнялось действие(например отправить почту).

tooncheg
() автор топика
Ответ на: комментарий от tooncheg

Можно. Но рискну предположить, однострочник вам не нужен. Предлагаю всю логику программы запихнуть внутрь файла file.pl:

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

my ($line_number, @results);

# Читаю выхлоп `nbtscan` построчно
open my $fh, 'cat nbtscan.txt |';  # Заменить `cat ...` на `nbtscan ...`
while (my $line = <$fh>) {
    chomp $line;
    $line_number += 1;

    # Первые четыре строки - это мусор. Игнорю его:
    next if $line_number < 5;

    # Собираю результаты
    my @line_parts = split /\s+/, $line;
    my $result = $line_parts[0] . "\t" . $line_parts[1];
    push @results, $result;
}
close $fh;

# Если есть результаты, с ними можно что-нибудь сделать
for my $result (@results) {
    # Например, вывести на экран:
    say $result;

    # Или отправить на почту...
}
evbogdanov
()
Ответ на: комментарий от tooncheg

Пересиль себя, сохрани в файл, а потом используй вот так:

cat file | ./script.pl where_to_save

Будет дописывать новые записи в конец where_to_save

#!/usr/bin/env perl

use strict;
use warnings;

use English;

# HowTo send email: perldoc perlfaq9
# or perldoc Email::Sender::Manual::QuickStart
use Email::Sender::Transport::SMTP;
use Email::Sender::Simple qw(sendmail);
use Email::MIME;

use constant {
  SASL_USERNAME => 'pupkin@mail.ru',
  SASL_PASSWORD => 'qwerqwer',
  SMTP_SERVER   => 'smtp.mail.ru',
  EMAIL_SUBJECT => 'Yet another message from perl script!',
  HEADER_SIZE   => 4,
};

my $file = $ARGV[0];

defined($file)  or die 'No file name specified!';

open( my $fh, ">>$file" ) or die "Can't open file: '$file' ($OS_ERROR)";

my @lines_buff = ();

while( !eof(STDIN) ) {

  my $line = <STDIN>;
  next if $INPUT_LINE_NUMBER <= HEADER_SIZE;

  push @lines_buff, $line;

  print $fh $line;
}

if ( @lines_buff ) {

  my $tansport_obj = Email::Sender::Transport::SMTP->new(
    host => SMTP_SERVER,
    ssl  => 1,
    sasl_username => SASL_USERNAME,
    sasl_password => SASL_PASSWORD,
  );

  my $msg = Email::MIME->create(
    header_str => [
      From    => SASL_USERNAME,
      To      => SASL_USERNAME,
      Subject => EMAIL_SUBJECT,
    ],
    attributes => {
      encoding => 'quoted-printable',
      charset  => 'utf-8',
    },
    body_str => join '', @lines_buff,
  );

  sendmail($msg, {transport=>$tansport_obj});
}
perl5_guy ★★★★★
()
Ответ на: комментарий от evbogdanov

Подсказать сможете?

#!/usr/bin/perl

use Time::Piece;
#use warnings;
#use strict;
use feature 'say';

my $cmd='nbtscan 192.168.0.0/16 2>/dev/null | sed "1,4D"| sed "s/\( \)\+/\t/g" | cut -f "1 2 5"> temp_ip_name_mac.list';
my $file = "ip_name_mac.list";
my @listIM1; # List IP and MAC
my @listIM2; # List IP and MAC

system ($cmd);

open (DATA1, "temp_ip_name_mac.list") or die $!;
open (DATA2, "ip_name_mac.list") or die $!;

while (<DATA1>) {
        chomp;
        next if /^\s*#/; # ignore comments
        my @f = split /\s/, $_;
        my %hash;
        @hash{'IP','NAME','MAC'} = @f;
        push @listIM1, \%hash;

}

while (<DATA2>) {
        chomp;
        next if /^\s*#/; # ignore comments
        my @f = split /\s/, $_;
        my %hash;
        @hash{'IP','NAME','MAC'} = @f;
        push @listIM2, \%hash;

}

Задача следующая. Сравнить элементы IP. Если IP+МАС найден в обоих списках, то вывести, то ничего не делать. Если не найдено, то сравнить IP списков. IP найден - вывести сообщение о том что МАС различаются. IP не надет добавить строку в файл.

foreach my $seq1 (@listIM1) { 
	foreach my $seq2 (@listIM2) {
  
	 if ("$seq1->{IP} && $seq1->{MAC}" eq "$seq2->{IP} && $seq2->{MAC}") {
         } elsif ("$seq1->{IP}" eq "$seq2->{IP}") {
		print "$seq1->{IP}\t$seq1->{NAME}\t$seq1->{MAC}. Реальная запись -->  $seq2->{IP}\t$seq2->{NAME}\t$seq2->{MAC} \n";    	
	 } elsif () {

	 } else {
	 	
	 }
 }
}

Все вроде хорошо до момента, если не найден IP, то добавить строку. Как это должно быть.

tooncheg
() автор топика
Ответ на: комментарий от tooncheg

Задача следующая. Сравнить элементы IP. Если IP+МАС найден в обоих списках, то ничего не делать. Если не найдено, то сравнить IP списков. IP найден - вывести сообщение о том что МАС различаются. IP не наден добавить строку в файл.

tooncheg
() автор топика
Ответ на: комментарий от tooncheg

Как-то так:

#!/usr/bin/perl

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

use constant {
    COMMAND => 'nbtscan 192.168.0.0/16 2>/dev/null',
    COMMAND_USEFUL_LINES_START_AT => 5,
    FILE => 'ip_name_mac.list',
};


sub get_results_from_command {
    my ($line_number, @results);
    open(my $fh, COMMAND.' |') or die $!;
    while (my $line = <$fh>) {
        chomp $line;
        $line_number += 1;
        next if $line_number < COMMAND_USEFUL_LINES_START_AT;
        my @line_parts = split /\s+/, $line;
        push @results, {IP => $line_parts[0],
                        NAME => $line_parts[1],
                        MAC => $line_parts[4]};
    }
    close $fh;
    return \@results;
}

sub get_results_from_file {
    my @results;
    open(my $fh, '<', FILE) or die $!;
    while (<$fh>) {
        chomp;
        next if /^\s*#/;  # ignore comments
        my %result;
        @result{'IP','NAME','MAC'} = split /\s+/, $_;
        push @results, \%result;
    }
    close $fh;
    return \@results;
}

sub main {
    my ($results1, $results2) = (get_results_from_command,
                                 get_results_from_file);

    open(my $fh, '>>', FILE) or die $!;
    for my $res1 (@$results1) {
        my @results2_found = grep { $_->{IP} eq $res1->{IP} } @$results2;
        if (@results2_found) {
            for my $res2 (@results2_found) {
                if ($res2->{MAC} ne $res1->{MAC}) {
                    say 'Different MAC: ' . $res2->{MAC} . ' for IP: ' . $res2->{IP};
                }
            }
        }
        else {
            # IP not found. Save it!
            say $fh "$res1->{IP} $res1->{NAME} $res1->{MAC}";
        }
    }
    close $fh;
}

main();

evbogdanov
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.