Оболочка Linux: Base64 Decode с удалением разрывов строк - PullRequest
0 голосов
/ 23 мая 2018

У меня есть файл, где каждая строка представляет собой XML-документ в кодировке base64.Декодированные XML-документы могут содержать символы новой строки.Я хотел бы выполнить поиск по каждому XML-документу, содержащему данное слово.

Проблема в том, что когда я декодирую строки файла, у меня есть несколько строк для каждой строки в кодировке base64, и я не могу выполнить какой-либо grepБольше.Мне нужно что-то вроде base64 decode + remove line breaks за один шаг.

Как мне добиться этого в оболочке Linux?У меня есть Python, Perl и awk.

>cat fileContainingBase64EncodedXMLsInEachLine.txt | what should I write here?

Ввод:

PGZvbz4NCjxiYXIvPg0KPC9mb28+
PGZvbz4NCjxodWh1Lz4NCjwvZm9vPg==
PGZvbz4NCjxiYXJvbWV0ZXIvPg0KPC9mb28+

Ожидаемый вывод

Допустим, я хочу XML-документы, содержащие 'bar'

<foo>
<bar/>
</foo>
<foo>
<barometer/>
</foo>

Пример моей проблемы

>cat fileContainingBase64EncodedXMLsInEachLine.txt | base64 --decode | grep bar

Поставляет:

<bar/>
<barometer/>

Поэтому у меня нет полных XML-документов, содержащих bar и barometer.

Ответы [ 5 ]

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

Perl на помощь:

perl -MMIME::Base64 -nE '$_=decode_base64($_);/bar/&&say' fileContaining...txt

или

cat fileContaining...txt | perl -MMIME::Base64 -nE'$_=decode_base64($_);/bar/&&say'
0 голосов
/ 23 мая 2018

обновление: , если вы знаете, что имя первого узла <foo>, тогда вы можете просто сделать:

$ echo "<head>$(base -decode <file>)</head>" | \
  xmlstarlet sel -t -m '//bar/ancestor::foo' -c .

Он выбирает предка с именем foo узланазывается bar, поскольку foo является первым xml-узлом, он выберет запрошенный xml-файл.

оригинальный ответ ниже:

Использование xmlstarletВозможно, вы захотите сделать это

$ echo "<head>$(base -decode <file>)</head>" | \
  xmlstarlet sel -t -m '//bar/ancestor::*[last()-1]' -c .

Это, по сути, выберет полное xml-дерево предков узла 'bar', но оно пойдет только на правильную глубину.

Я добавилдополнительный узел head, чтобы сделать полную строку допустимым xml файлом.Таким образом, вам нужно печатать только с первого узла и далее.

echo будет производить что-то вроде (немного другая версия):

<head> 
  <foo /> 
  <foo> 
    <barometer /> 
  </foo> 
  <foo> 
    <DDD> 
      <BBB/> 
      <bar /> 
    </DDD> 
  </foo> 
</head>

xmlstarlet сделает выбор шаблонана основе xpath //bar/ancestor::*, что приводит к следующему набору совпадений

  • <bar />
  • <DDD><BBB /><bar /></DDD>
  • <foo><DDD><BBB /><bar /></DDD></foo>
  • <head> everything </ head>

Нас интересует предпоследний, то есть [last()-1], и мы просим распечатать его копию -c .

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

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

#!/bin/bash

while IFS='' read -r line
do
    echo -n "$line" | base64 --decode | tr -d '\r\n'
    echo
done < fileContainingBase64EncodedXMLsInEachLine.txt
0 голосов
/ 23 мая 2018

Вот некоторый код Python, который принимает имя файла, за которым следует слово поиска в командной строке.Как обычно, если какой-либо аргумент содержит пробелы, он должен быть заключен в кавычки.

import sys
from base64 import b64decode

fname, pattern = sys.argv[1:]
with open(fname) as f:
    for row in f:
        row = b64decode(row).decode()
        if pattern in row:
            print(row, end='\n\n')

Запуск этого для ваших данных с помощью "bar", поскольку шаблон arg дает:

<foo>
<bar/>
</foo>

<foo>
<barometer/>
</foo>

Чтобы применить свои довольно ржавые навыки awk, я решил написать для этого командную строку awk.Он использует стандартную команду base64 для декодирования.

awk 'BEGIN{cmd="base64 -d"}; {print |& cmd; close(cmd,"to"); z=""; while(cmd |& getline s) z=z s "\n"; close(cmd); if (z~pat)print z}' pat='bar' testdata_b64.txt

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

Обратите внимание, что шаблоны регулярных выражений требуют двойного экранирования, например, pat='\\<bar\\>' соответствует слову bar.

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

вы можете попробовать следующий скрипт Python.Это не командная строка, но это должно дать вам то, что вы хотите.Для использования выполните:

>python3 get_xml.py SEARCHSTRING FILENAME

для вас пример:

<foo>
<bar/>
</foo>
<foo>
<barometer/>
</foo>

скрипт:

import base64
import sys
script_name = sys.argv[0]
search_string = sys.argv[1]
filename = sys.argv[2]
print("[+] ({}) search for {}".format(script_name,search_string,filename))
with open(filename,"r") as xml_in:
    nextline = xml_in.readline()
    while nextline != '':
        xml = base64.b64decode(nextline).decode("utf-8").rstrip()
        if search_string in xml:
            print(xml)
        nextline = xml_in.readline()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...