Как мне извлечь несколько строк, разделенных запятыми, из файла журнала?

Это происходило со мной даже в других программах, таких как uGet, загрузчик, который также имеет параметр "открыть содержащий папка".

Проблема, как указано здесь , запускается определенными программами.

Лучшее решение - создать или отредактировать ~ / .local / share / applications / mimeapps.list : отредактируйте строку, которая начинается с inode / directory = , и добавьте имя используемого файлового менеджера, если его еще нет; если это уже есть, но другая программа указана там первой, сначала поместите файловый менеджер (если вам нужны другие программы для открытия папок).

Для файлов Pantheon это должно быть похоже на

[Default Applications]
inode/directory=org.pantheon.files.desktop; 

. Если среда рабочего стола несовместима с freedesktop, как мой Manjaro Cinnamon, создаваемый / редактируемый файл должен быть ~ / .local / share / applications / mimeinfo. cache вот так:

[MIME Cache]
inode/directory=org.pantheon.files.desktop; 

Вы должны публиковать вопросы по elementaryOS на собственном сайте stackexchange: https://elementaryos.stackexchange.com/

1
03.01.2017, 16:53
7 ответов

Решение с GNU awk :

gawk -v OFS= -v FPAT=',(srcip|srczone|protocol|dstip|dstzone|dstport|rule_name)=[^,]*' -e 'NF > 0 { $1=$1; print }'

Здесь я использую особенность GNU awk : с переменной FPAT , I ' m с указанием формата полей с помощью регулярного выражения, так что каждой части строки, соответствующей регулярному выражению, присваивается значение $ 1 ... $ n . Затем я назначаю $ 1 на $ 1 , чтобы $ 0 был восстановлен с нуля, используя только $ 1 ... $ n .

1
27.01.2020, 23:14

Решение

Вы можете использовать команду cut . В вашем случае вы можете указать ему три параметра:

  • -d ',' : это разделитель вашей строки. В вашем случае это , . Вы можете заменить разделитель на любой, какой захотите.
  • -f 4,7,8 : представляет часть строки, которую вы хотите получить (разделенную запятой). В данном случае это 4-я, 7-я и 8-я части. Вы можете указать диапазон, используя, например, эту форму 1-8 .
  • file.ext : это ваш файл журнала.

Примеры использования

Допустим, ваш файл журнала - file.log (очень креативное имя):

  • cut -d ',' -f 1-5 file.log : Это даст вам date = "2017-01-03 08:30:02 -0500" fac = f_kernel_ipfilter, area = a_general_area

  • cut -d ',' -f 3,5,6 file.log : это даст вам fac = f_kernel_ipfilter, type = t_attack, pri = p_major

  • cut -d ',' -f 4 file.log : Это даст вам type = t_attack

Примечание

cut будет проходить через все строки вашего файла. Если вы хотите пропустить строки, которые не содержат указанного вами разделителя, используйте параметр -s .

0
27.01.2020, 23:14

Я немного задерживаюсь с этим, но предлагаю предложение - такого рода данные вполне подходят для сопоставления хэша:

#!/usr/bin/env perl

use strict;
use warnings;
#for debugging - can be removed;
use Data::Dumper;

my @fields = qw ( srcip srczone protocol dstip dstzone dstport rule_name );

#read STDIN or files specified on command line (just like grep/sed/awk)
while ( <> ) {

   #split commas
   #then read key-value pairs. 
   my %row = map { m/(.*)=(.*)/ } split /,/;
   #for debugging:
   print Dumper \%row;

   #print fields tab-separated and in order as above. 
   print join "\t", @row{@fields};
}

Это немного сложнее, потому что у вас есть список полей, которые нужно разобрать. Но:

perl -lane -F, 'BEGIN { @k = qw ( srcip srczone protocol dstip dstzone dstport rule_name ) } %r = map { m/(.*)=(.*)/ } @F; print join "\t", @r{@k}'
1
27.01.2020, 23:14

Поместите нужные шаблоны регулярных выражений в файл и используйте egrep.

Ваш файл (назовем его filter.txt):

srcip=(.*?),
srczone=(.*?),
....

Ваша команда:

grep -Eof filters.txt logfile.txt
0
27.01.2020, 23:14

Вот быстрый и грязный подход с использованием perl :

$ perl -F, -lane '@l = grep {/srcip|srczone|protocol|dstip|dstzone|dstport|rule_name/} @F; 
                  print join ",",@l' file 
srcip=1.1.1.1,srczone=internal,protocol=6,dstip=2.2.2.2,dstport=80,dstzone=external,rule_name=Deny_All

-a заставляет perl действовать как awk и разбивать свои входные строки на символ, заданный - F , сохранив их как элементы массива @F . Затем мы grep массив и сохраняем элементы, соответствующие вашим целевым словам в массиве @l , и, наконец, печатаем @l , соединенные запятыми.

Обратите внимание, что это не удастся, если какой-либо из ваших паттернов может быть подшаблоном (скажем, у вас есть foo = bar и foobar = baz ).

Для более длинных списков целевых шаблонов (при условии, что вы не хотите писать фактический скрипт) вы можете сохранить их в массиве и присоединить к ним с помощью | , чтобы создать регулярное выражение для grep. И добавляя \ b вокруг каждого шаблона, вы также защищаете от совпадения подшаблонов. Если мы также удалим ненужный массив temp, мы получим:

$ perl -F, -lane '
    BEGIN{
     $pat="\\b" . join "\\b|",qw(srcip= srczone= protocol= dstip= dstzone= dstport= rule_name=)
    } print join ",",grep {/$pat/}@F' file 
srcip=1.1.1.1,srczone=internal,protocol=6,dstip=2.2.2.2,dstport=80,dstzone=external,rule_name=Deny_All

Наш постоянный эксперт сказал, что это невозможно сделать в оболочке bourne независимо от sed awk или [. . ..] От вашего командира

Извините, но это явный абсурд. Вот один (из многих) способов сделать это в каждом из этих инструментов:

  1. Bourne (снова) оболочка. Не используйте это, я показываю это только для того, чтобы продемонстрировать, что это возможно.

     $ pat = (srcip = srczone = протокол = dstip = dstzone = dstport = имя_правила =); 
     $ o = ""; пока IFS =, прочтите поля -a; выполните 
    вместо f в "$ {fields [@]}"; сделать 
    вместо пат в "$ {pat [@]}"; сделать 
     [[$ f = ~ $ pat]] && o = "$ f, $ o" 
    готово 
    готово 
    готово 
  2. Awk

    Сохраните целевые шаблоны в файле:

     $ cat patterns 
    srcip 
    srczone 
    протокол 
    dstip 
    dstzone 
    dstport 
    имя_правила 
     

    Затем:

     $ awk -F, '(NR == FNR) {
    пат [$ 0] ++; 
    далее; 
    } 
     {
    for (i = 1; i <= NF; i ++) {
    split ($ i, a, знак равно 
    if (a [1] в pat) {
    printf "% s =% s,", a [1], a [2] 
    } 
     } 
    файл шаблонов print "" 
    } '| sed 's /, $ //' 
    srcip = 1.1.1.1, srczone = internal, protocol = 6, dstip = 2.2.2.2, dstport = 80, dstzone = external, rule_name = Deny_All 
     
  3. sed (и оболочка)

     $ pat = (srcip = srczone = protocol = dstip = dstzone = dstport = rule_name =); 
     $ for p в $ {pat [@]} ; do 
    sed -E "s /.*($ p [^,] *). * / \ 1 /" file; сделано | 
    sed ': a; N; $! Ba; s / \ n /, / g' 
    srcip = 1.1.1.1, srczone = internal, protocol = 6, dstip = 2.2.2.2, dstzone = external, dstport = 80, rule_name = Deny_All 
     
  4. Оболочка Борна (или любая оболочка POSIX) + sed (как для 1., не делайте этого, это возможно, но глупо)

     $ установите srcip = srczone = protocol = dstip = dstzone = dstport = rule_name = 
     $ для f в "$ @"; do sed "s /.*\($ f [^,] * \). * / \ 1 /" файл; сделано | sed ': a; N; $! ba; s / \ n /, / g' 
    srcip = 1.1.1.1, srczone = internal, protocol = 6, dstip = 2.2.2.2, dstzone = external, dstport = 80, rule_name = Deny_All 
     
4
27.01.2020, 23:14

bash

IFS=, read -r -a fields <<< "$date"
results=()
for keyval in "${fields[@]}"; do 
    IFS='=' read -r key value <<< "$keyval"
    case $key in 
        srcip|srczone|protocol|dstip|dstzone|dstport|rule_name) results+=("$keyval")
    esac
done
(IFS=,; echo "${results[*]}")
srcip=1.1.1.1,srczone=internal,protocol=6,dstip=2.2.2.2,dstport=80,dstzone=external,rule_name=Deny_All
0
27.01.2020, 23:14

Я пробовал использовать только sed

sed -r 'h;
s/.*(srcip=[^,]*).*/\1/; H; g; 
s/.*(srczone=[^,]*).*/\1/; H; g; 
s/.*(protocol=[^,]*).*/\1/; H; g; 
s/.*(dstip=[^,]*).*/\1/; H; g; 
s/.*(dstport=[^,]*).*/\1/; H; g; 
s/.*(dstzone=[^,]*).*/\1/; H; g; 
s/.*(rule_name=[^,]*).*/\1/; H; g; 
s/.*\n//M; 
s/\n/,/g;
' file
0
27.01.2020, 23:14

Теги

Похожие вопросы