Как получить два шаблона одновременно и получить результат в одной строке? - PullRequest
0 голосов
/ 25 мая 2018

У меня есть существующие файлы журналов, в которых, помимо прочего, есть строки следующего типа:

2018-05-14T10:10:22.769029+03:00 timom usbmonitor: [INFORMATION 6] [FILE: UsbChecker.cpp:51][FUNC: vendorCheck][MSG: USB vendors changed: "0403 14e1 05e3 05e3 03f0 0403 0bda 1d6b 1d6b 1d6b 1d6b 1d6b 1d6b 1d6b" ]

Из этих файлов я хочу выделить строки выше, чтобы получить метку времени с начала и текст внутрицитаты, чтобы у меня был хороший и компактный вывод:

2018-05-14T10:10:22.769029+03:00 0403 14e1 05e3 05e3 03f0 0403 0bda 1d6b 1d6b 1d6b 1d6b 1d6b 1d6b 1d6b

Есть ли способ сделать это с помощью одной строки?
Я ищу способ эффективно получить желаемоевывод без необходимости зацикливания на заштрихованных линиях.У меня есть тысячи файлов журналов, каждый из которых может иметь сотни совпадений, поэтому grep / sed / what должен быть эффективным.

До сих пор я делал это так:

#!/bin/bash
INPUTDIR=
OUTPUTDIR=
while getopts ":h:d:o:" OPTION; do
    case $OPTION in
        h)
            usage
            exit 1
            ;;
        d)
            INPUTDIR=$OPTARG
            ;;
        o)
            OUTPUTDIR=$OPTARG
            ;;
        ?)
            usage
            exit 1
            ;;
    esac
done
if [ -z $INPUTDIR ] || [ -z $OUTPUTDIR ]; then
    echo "BAD ARGUMENTS: both directories aren't given" >&2
    usage
    exit 1
fi
OUTPUTFILE="$(date +%Y%m%d%H%M%S)-usb-analysis-summary"
for i in $( ls $INPUTDIR ); do
    # Interesting files are of format <number>_<number>
    if [ $(echo "$i" | grep -Ev "^[0-9]+_[0-9]+$") ] ; then
        echo "Skipping $i"
        continue
    fi
    grep vendorCheck $INPUTDIR/$i | while read -r l ; do
        # We do know timestamp is 32 characters long. GEFN
        echo "$l" | sed -r "s|^(.{32}).*changed: \"(.*)\".*|\1 \2|" >>$OUTPUTFILE
    done
done

Но это не оптимально, так как теперь я зацикливаю файлы, а затем зацикливаю совпадения grep из каждого файла.

Я пытался

grep "vendorCheck" $INPUTDIR/$i | sed -r "s|^(.{32}).*changed: \"(.*)\".*|\1 \2|"

Но это удаляет разрывы строк.
Затемесли я помещаю несколько шаблонов в один grep, у меня также возникают проблемы с форматированием;Мне нужно получить метку времени и текст внутри кавычек в одну строку, а затем аналогично следующей строке.

1 Ответ

0 голосов
/ 25 мая 2018

Sed может выполнять подбор и сопоставление выделенных строк одновременно.

Вы также можете использовать $(...) для генерации списка входных файлов sed, так что вы действительно можете поместить все это в одну строку, я думаю, но это ls не идеально, и вы сказали, что вам нужны имена файловв приведенном ниже комментарии, так что ...

Вместо

sed -r -n '/vendorCheck/{s/(.{32}).*changed: \"(.*)\"/\1 \2/; p;}' $( ls -1 $INPUTDIR | egrep '^[0-9]+_[0-9]+$' ) >> $OUTPUTFILE

Вы можете вставить какой-нибудь пробел, чтобы сделать его немного менее уродливым, не изменяя функциональность "одной строки", иЦикл может заменить ls:

for f in $INPUTDIR/[0-9]*_[0-9]* # limit input, not a definitive check
do echo "$f" | egrep '^[0-9]+_[0-9]+$' || continue # CONFIRM filename match
   [[ -f $f ]] || continue  # and assert file, not dir
   sed -r -n "/vendorCheck/{
      s/(.{32}).*changed: \"(.*)\"/\1 \2/;
      s/^/$f: /;
      p;
   }" "$f" # the "s/^/$f: /;" is a placeholder of your need for the name
done >> $OUTPUTFILE

ПРИМЕЧАНИЕ: удалили мои тестовые данные, так что это доработка не была проверена так тщательно.Дайте мне знать, если кто-нибудь увидит опечатку.

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