Оценка команды с помощью Awk - PullRequest
2 голосов
/ 12 октября 2011

Проблема в том, что: у меня есть разные txt-файлы, в которых зарегистрированы временная метка и ip-адрес для каждого вредоносного пакета, поступающего на сервер. Что я хочу сделать, это создать еще один текстовый файл, который показывает, для каждого ip, в первый раз, когда приходит вредоносный пакет.

В общем, я хочу сделать что-то вроде этого:

for every  line in file.txt
 if (ip is not present in list.txt)
 copy timestamp and ip in list.txt

Я использую awk для этого. Основная проблема - «если ip отсутствует в list.txt». Я делаю это:

 {    a=$( grep -w "$3" list.txt | wc -c );
    if ( a == 0 )
   {
     #copy timestamp and ip in list.txt
   }

(я использую $ 3, потому что IP-адрес находится в третьем столбце исходного файла)

Я не знаю, как заставить awk оценивать функцию grep. Я тоже пробовал с помощью обратных кавычек, но это не сработало. Кто-нибудь может дать мне подсказку?

Я тестирую свой скрипт на тестовом файле следующим образом:

10  192.168.1.1
11  192.168.1.2
12  192.165.2.4
13  122.11.22.11    
13  192.168.1.1
13  192.168.1.2
13  122.11.22.11
14  122.11.22.11
15  122.11.22.11
15  122.11.22.144
15  122.11.2.11
15  122.11.22.111

Что я должен получить:

10  192.168.1.1
11  192.168.1.2
12  192.165.2.4
13  122.11.22.11    
15  122.11.22.144
15  122.11.2.11
15  122.11.22.111

Благодаря вашей помощи мне удалось создать скрипт, который соответствует моим потребностям:

awk '
FILENAME == ARGV[1] {
    ip[$2] = 1
    next
}
! ($2 in ip) {
    print $1, $2 >> ARGV[1]
    ip[$2] = 1
}
' list.txt file.txt 

Ответы [ 4 ]

3 голосов
/ 12 октября 2011

Интерпретируя вопрос как «Как я могу оценить статус команды из awk?», Просто используйте system.

{
  if( system( "cmd" ) == 0 ) {
    # the command succeeded
  {
}

Итак, в вашем случае просто выполните:*

Возможно, вы захотите пересмотреть свой подход к проблеме.Grepping каждый раз требует больших вычислительных ресурсов, и есть более эффективные способы решения этой проблемы.(Прочитайте, например, list.txt один раз в массив.)

Также обратите внимание, что вам не нужно использовать wc.grep терпит неудачу, если это не соответствует строке.Используйте возвращаемое значение, а не анализируйте вывод.

2 голосов
/ 12 октября 2011

Это сохранит результат выполнения в переменную a

BEGIN {  } 
{
"grep -w \"$3\" list.txt | wc -c" | getline a
print a
}
END   {}
1 голос
/ 12 октября 2011

Но на самом деле вы хотите, чтобы awk сначала прочитал файл list.txt, а затем обработал другой файл с данными list.txt в памяти.Это позволит вам избежать вызова system() для каждой строки.

Я предполагаю, что ip находится в 1-м столбце list.txt.

Когда вы говорите copy timestamp and ip in list.txt, я предполагаю, что выхотите добавить некоторую информацию из текущей строки file.txt в файл list.txt.

awk '
    FILENAME == ARGV[1] {
        ip[$1] = 1
        next
    }
    ! ($3 in ip) {
        print $3, $(whatevever_column_holds_timestamp) >> ARGV[1]
    }
' list.txt file.txt

Учитывая пример файла и упрощенные требования обновления вашего вопроса:

awk '! seen[$2]++' filename

даст результаты, которые вы видели.Эта awk-программа выведет строку, если IP еще не виден.

1 голос
/ 12 октября 2011

Вы хотите использовать getline :

BEGIN {
    "date" | getline current_time
     close("date")
     print "Report printed on " current_time
}

Это берет вывод date и помещает его в переменную current_time. Вы должны быть в состоянии сделать то же самое со своим grep | wc -l.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...