Bash: чтение вывода в строку со специальными символами

Я использую TShark для чтения TCP-потоков PCAP в файл заданного формата. Мой код:

#!/bin/bash
OUT="*/temp/Temp.txt"
NEW="\"REQ:"
i=0
echo "Generating conversations..."
echo ""  > $OUT
while [ "$COUNT" != 1 ]
do
    BLOCK="$(tshark -r */browser.pcap -q -z follow,tcp,ascii,$i)"
    SUB=$(echo "$BLOCK" | sed -n '5p')
    PORT=${SUB##*:}
    BLOCK="${BLOCK//$'\t'/\"RES:}"
    BLOCK=$(echo "$BLOCK" | tail -n +6)
    BLOCK=$(echo "$BLOCK" | head -n -1)
    COUNT=$(echo "$BLOCK" | wc -l)
    BLOCK=$(echo "$BLOCK" | awk '{print $j"\""}')
    j=1
    while [ $j -lt $(($COUNT+2)) ]
    do
        CHECK=$(echo "$BLOCK" | sed $j'q;d')
        PREF=${CHECK:0:5}
        if [ "$PREF" != "\"RES:" ]; then
            CHECK=$NEW$CHECK
            BLOCK=$(echo "$BLOCK" | sed $j's/.*/'$CHECK'/')
        fi
        j=$(($j+1))
    done
    if [ "$COUNT" != 1 ]; then
        echo ""  >> $OUT
        echo "\$" >> $OUT
        echo "tag = \"gen."$i"\"" >> $OUT
        echo "port = \""$PORT"\"" >> $OUT
        echo "base = \"TCP\"" >> $OUT
        echo "payloads:" >> $OUT
        echo "$BLOCK" >> $OUT
        echo "Generated conversation "$i
    fi
    i=$(($i+1))
done
echo "Generation complete!"

Когда я запускаю это, я получаю следующую ошибку для каждого прочитанного разговора:

> sed: -e expression #1, char 18: unterminated `s' command

Я считаю, что проблема заключается в вызове TShark в строке 9. Первоначально я использовал «сырой» аргумент для команды, которая выводит необработанные шестнадцатеричные данные. Это сработало и вышло правильно. Однако моя задача требует вывода данных ASCII. Изменение «raw» на «ascii» (оба распознаются TShark) вызывает вышеупомянутые ошибки. Я полагаю, это связано с тем, что данные ASCII в прочитанных пакетах содержат специальные символы; небольшой фрагмент данных, сгенерированный строкой 9 в командной строке:

..7.<.......Y.|.$.......2...W...v.'#

Мой вопрос: являются ли специальные символы в данных ASCII, которые я анализирую, причиной ошибок sed? Если да, то как я могу заставить bash игнорировать их? Спасибо!

Изменить. В конечном итоге я пытаюсь получить вывод этой команды TShark, который выглядит так...

===================================================================
Follow: tcp,raw
Filter: tcp.stream eq 4
Node 0: 10.211.55.3:58733
Node 1: 157.127.239.146:80
47455420687474703a2f2f73656d696e617270726f6a656374732e6f72672f6373732e7068703f7374796c6573686565743d393620485454502f312e310d0a486f73743a2073656d696e617270726f6a656374732e6f72670d0a557365722d4167656e743a204d6f7a696c6c612f352e3020285831313b204c696e7578207838365f36343b2072763a33382e3029204765636b6f2f32303130303130312046697265666f782f33382e300d0a4163636570743a20746578742f6373732c2a2f2a3b713d302e310d0a4163636570742d4c616e67756167653a20656e2d55532c656e3b713d302e350d0a4163636570742d456e636f64696e673a20677a69702c206465666c6174650d0a526566657265723a20687474703a2f2f73656d696e617270726f6a656374732e6f72672f632f74736861726b2d666f6c6c6f772d7463702d73747265616d0d0a436f6f6b69653a205f5f6366647569643d646564613432383039663566623634356461663239333963366235336565653764313433373734383236323b206d7962625b6c61737476697369745d3d313433373734383333353b206d7962625b6c6173746163746976655d3d313433373734383333353b207369643d31663739303463373761383761656234363537306131636161316462336161310d0a436f6e6e656374696f6e3a206b6565702d616c6976650d0a0d0a
    485454502f312e3120323030204f4b0d0a446174653a204672692c203234204a756c20323031352031343a33313a303420474d540d0a436f6e74656e742d547970653a20746578742f6373730d0a582d506f77657265642d42793a205048502f352e342e31360d0a5365727665723a20636c6f7564666c6172652d6e67696e780d0a43462d5241593a20323062303533396434326436313365332d4c41580d0a436f6e74656e742d456e636f64696e673a20677a69700d0a436f6e74656e742d4c656e6774683a203134320d0a4167653a20300d0a5669613a20312e31206e657070737730390d0a0d0a1f8b08000000000000036c8cbd0a03211084ebf52916ac13f2db689bcb6b04bd15919caeac060e42de3d981469325f37df305bcf4ee896436b2e067c2af06ebe47e14721837aba0eac8299171683faf88955e05928c8a6733578a82b365e12a1be9c063fefb977ceff27d511a5120d9eeb6a1564273195efe37e37aa970278030000ffff0300cc348afaa1000000
47455420687474703a2f2f7777772e676f6f676c652d616e616c79746963732e636f6d2f616e616c79746963732e6a7320485454502f312e310d0a486f73743a207777772e676f6f676c652d616e616c79746963732e636f6d0d0a557365722d4167656e743a204d6f7a696c6c612f352e3020285831313b204c696e7578207838365f36343b2072763a33382e3029204765636b6f2f32303130303130312046697265666f782f33382e300d0a4163636570743a202a2f2a0d0a4163636570742d4c616e67756167653a20656e2d55532c656e3b713d302e350d0a4163636570742d456e636f64696e673a20677a69702c206465666c6174650d0a526566657265723a20687474703a2f2f73656d696e617270726f6a656374732e6f72672f632f74736861726b2d666f6c6c6f772d7463702d73747265616d0d0a436f6e6e656374696f6e3a206b6565702d616c6976650d0a49662d4d6f6469666965642d53696e63653a205468752c203039204a756c20323031352032333a35303a353620474d540d0a0d0a
    485454502f312e3120333034204e6f74204d6f6469666965640d0a446174653a204672692c203234204a756c20323031352031343a33303a353520474d540d0a457870697265733a204672692c203234204a756c20323031352031353a35313a343120474d540d0a43616368652d436f6e74726f6c3a207075626c69632c206d61782d6167653d373230300d0a566172793a204163636570742d456e636f64696e670d0a436f6e6e656374696f6e3a20636c6f73650d0a5669613a20312e31206e657070737730390d0a0d0a
===================================================================

... в пользовательский формат для чтения программой. Приведенный выше вывод представлен в рабочем необработанном шестнадцатеричном формате данных. Пользовательский формат для соответствующего диалога выглядит следующим образом:

$
tag = "gen.4"
port = "58733"
base = "TCP"
payloads:
"REQ:47455420687474703a2f2f73656d696e617270726f6a656374732e6f72672f6373732e7068703f7374796c6573686565743d393620485454502f312e310d0a486f73743a2073656d696e617270726f6a656374732e6f72670d0a557365722d4167656e743a204d6f7a696c6c612f352e3020285831313b204c696e7578207838365f36343b2072763a33382e3029204765636b6f2f32303130303130312046697265666f782f33382e300d0a4163636570743a20746578742f6373732c2a2f2a3b713d302e310d0a4163636570742d4c616e67756167653a20656e2d55532c656e3b713d302e350d0a4163636570742d456e636f64696e673a20677a69702c206465666c6174650d0a526566657265723a20687474703a2f2f73656d696e617270726f6a656374732e6f72672f632f74736861726b2d666f6c6c6f772d7463702d73747265616d0d0a436f6f6b69653a205f5f6366647569643d646564613432383039663566623634356461663239333963366235336565653764313433373734383236323b206d7962625b6c61737476697369745d3d313433373734383333353b206d7962625b6c6173746163746976655d3d313433373734383333353b207369643d31663739303463373761383761656234363537306131636161316462336161310d0a436f6e6e656374696f6e3a206b6565702d616c6976650d0a0d0a"
"RES:485454502f312e3120323030204f4b0d0a446174653a204672692c203234204a756c20323031352031343a33313a303420474d540d0a436f6e74656e742d547970653a20746578742f6373730d0a582d506f77657265642d42793a205048502f352e342e31360d0a5365727665723a20636c6f7564666c6172652d6e67696e780d0a43462d5241593a20323062303533396434326436313365332d4c41580d0a436f6e74656e742d456e636f64696e673a20677a69700d0a436f6e74656e742d4c656e6774683a203134320d0a4167653a20300d0a5669613a20312e31206e657070737730390d0a0d0a1f8b08000000000000036c8cbd0a03211084ebf52916ac13f2db689bcb6b04bd15919caeac060e42de3d981469325f37df305bcf4ee896436b2e067c2af06ebe47e14721837aba0eac8299171683faf88955e05928c8a6733578a82b365e12a1be9c063fefb977ceff27d511a5120d9eeb6a1564273195efe37e37aa970278030000ffff0300cc348afaa1000000"
"REQ:47455420687474703a2f2f7777772e676f6f676c652d616e616c79746963732e636f6d2f616e616c79746963732e6a7320485454502f312e310d0a486f73743a207777772e676f6f676c652d616e616c79746963732e636f6d0d0a557365722d4167656e743a204d6f7a696c6c612f352e3020285831313b204c696e7578207838365f36343b2072763a33382e3029204765636b6f2f32303130303130312046697265666f782f33382e300d0a4163636570743a202a2f2a0d0a4163636570742d4c616e67756167653a20656e2d55532c656e3b713d302e350d0a4163636570742d456e636f64696e673a20677a69702c206465666c6174650d0a526566657265723a20687474703a2f2f73656d696e617270726f6a656374732e6f72672f632f74736861726b2d666f6c6c6f772d7463702d73747265616d0d0a436f6e6e656374696f6e3a206b6565702d616c6976650d0a49662d4d6f6469666965642d53696e63653a205468752c203039204a756c20323031352032333a35303a353620474d540d0a0d0a"
"RES:485454502f312e3120333034204e6f74204d6f6469666965640d0a446174653a204672692c203234204a756c20323031352031343a33303a353520474d540d0a457870697265733a204672692c203234204a756c20323031352031353a35313a343120474d540d0a43616368652d436f6e74726f6c3a207075626c69632c206d61782d6167653d373230300d0a566172793a204163636570742d456e636f64696e670d0a436f6e6e656374696f6e3a20636c6f73650d0a5669613a20312e31206e657070737730390d0a0d0a"

person user2741375    schedule 24.07.2015    source источник
comment
Укажите расширение $CHECK (вообще всегда цитируйте расширения ваших переменных), и это решит часть вашей проблемы. У вас все еще будут проблемы с косой чертой/и т.д. в значении $CHECK, потому что sed не может отличить его. Использование awk может сделать это проще. Как бы то ни было, кажется, что это не может быть правильным подходом к вашей цели. Возможно, если бы вы объяснили основную задачу, вы могли бы получить более подходящую помощь для этого.   -  person Etan Reisner    schedule 24.07.2015


Ответы (1)


Вы можете указать bash не интерпретировать метасимволы, указав расширение переменной:

sed $j's/.*/'"$CHECK"'/'

На самом деле нет причин использовать одинарные кавычки в приведенном выше примере, поэтому вы можете просто заключить в двойные кавычки весь аргумент команды:

sed "${j}s/.*/$CHECK/"

Однако ни один из вышеперечисленных способов не скажет sed избегать интерпретации специальных символов в замещающей части команды s, поэтому, если $CHECK содержит /, это приведет к преждевременному прекращению выполнения команды. замена.

Итак, вопрос в том, есть ли лучший способ сделать это:

BLOCK=$(echo "$BLOCK" | sed $j's/.*/'$CHECK'/')

Судя по всему, цель состоит в том, чтобы заменить строку $j значения $BLOCK значением $CHECK. Один из способов сделать это, используя awk:

BLOCK="$(awk -v repl="$CHECK" 'NR==$j{print repl;next}1')"

Заметки:

  1. Хотя я не исправил это в своем примере, использование ВСЕХ ЗАГЛАВНЫХ букв для переменных оболочки является очень плохим стилем. Обычно переменные оболочки, написанные ЗАГЛАВНЫМИ БУКВАМИ, зарезервированы для использования в качестве известных экспортируемых переменных bash или системными утилитами (например, $PATH; $IFS; $TERM и т. д.). Ваши собственные переменные должны быть строчными, чтобы избежать конфликтов.

  2. Полный цикл, из которого взята команда, возможно, мог бы быть реализован более эффективно и чище (и понятнее) в awk. На основе примера вывода, вероятно, будет работать следующее:

    echo "Generating conversations..."
    i=0
    while 
        tshark -r */browser.pcap -q -z follow,tcp,ascii,$i |
        awk -v idx=$i -v '
          NR==4 { n = split($0, a, /:/); port = a[n]; }
          NR<6  { next; }
          /^=========/ { exit port != 0; }
          port  { print "$"
                  printf "tag = \"gen.%d\"" idx
                  print "port = \"%s\"" port
                  print "base = \"TCP\""
                  print "payloads:"
                  port = 0
                }
          /^\t/ { printf "\"RES:%s\"" substr($0, 2) "\""; next; }
                { printf "\"REQ:%s\"" $0 "\""; }
        ' >> $OUT;
    do
        echo "Generated conversation "$i
    done
    echo "Generation complete!"
    

    Я не пробовал. Вполне может глючить. Я не понимаю условия завершения, поэтому просто предположил. Я не уверен, действительно ли вы хотели извлечь номер порта из строки 5 (как в коде) или строки 4 (как в примере).

person rici    schedule 24.07.2015
comment
Эта строка предназначена для редактирования строки $j блока $BLOCK и добавления префикса REQ:. Это делается только в том случае, если для этой строки еще нет префикса RES:. Спасибо, я посмотрю, смогу ли я заставить это работать. - person user2741375; 24.07.2015
comment
@ user2741375: Вы делаете это для каждой строки? - person rici; 24.07.2015
comment
Да, я добавил немного больше к исходному вопросу, который показывает общую цель, если это поможет. - person user2741375; 24.07.2015
comment
@ user2741375: Вы уверены, что строки запроса и ответа никогда не содержат символы новой строки или табуляции? - person rici; 24.07.2015
comment
Да, все данные выводятся TShark одной строкой на запрос или ответ. Вкладки помещаются только перед строками ответов, чтобы указать, что они являются ответами, и я заменяю эти вкладки префиксом RES:. - person user2741375; 24.07.2015