Linux shell:Base64 Decode,删除换行符

时间:2018-05-23 08:35:27

标签: python shell perl awk

我有一个文件,其中每一行都是base64编码的XML文档。解码的XML文档可能包含新的行字符。我想grep出每个包含给定单词的XML文档。

问题在于,当我解码文件的行时,每个base64编码的行都有多行,我不能再对它进行grep了。我需要一步base64 decode + remove line breaks

如何在Linux shell中实现这一目标?我有Python,Perl和awk可用。

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

输入:

PGZvbz4NCjxiYXIvPg0KPC9mb28+
PGZvbz4NCjxodWh1Lz4NCjwvZm9vPg==
PGZvbz4NCjxiYXJvbWV0ZXIvPg0KPC9mb28+

预期产出

假设我想要包含'bar'的XML文档

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

我的问题的一个例子

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

提供了:

<bar/>
<barometer/>

所以我没有包含barbarometer的完整xml文档。

5 个答案:

答案 0 :(得分:2)

这是一些Python代码,它接受命令行上的搜索词后面的文件名。像往常一样,如果arg包含空格,则必须引用它。

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

答案 1 :(得分:1)

更新:如果您知道第一个节点名称是<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 .

这实际上选择了节点'bar'的祖先的完整xml树,但它只会达到正确的深度。

我添加了一个额外的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 .

答案 2 :(得分:1)

Perl救援:

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

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

答案 3 :(得分:0)

您可以尝试以下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()

答案 4 :(得分:0)

您可以在循环中使用tr删除每个XML文档的所有新行,如下所示:

#!/bin/bash

while IFS='' read -r line
do
    echo -n "$line" | base64 --decode | tr -d '\r\n'
    echo
done < fileContainingBase64EncodedXMLsInEachLine.txt