sed 捕获所有内容,直到使用变量作为字符串的模式

sed capture everything until pattern using variable as string

我有一堆表示类似于xml的文本。

<File>
    <abc1>
        <Hex>
            <item>
                <data>AB CD 34 43</data>
            </item>
         </Hex>
    </abc1>
</File>

我使用一个应用程序(ELF 64 位 LSB 可执行文件,x86-64,版本 1 (SYSV),动态链接,解释器 /lib64/ld-linux-x86-64.so.2,用于 GNU/Linux 2.6.32 , not stripped) 它将文件作为参数并对其进行解码。

我可以成功运行:

./application /tmp/file and it decodes correctly

我还可以捕获包括下面包含十六进制的行在内的所有内容(这很好用,但当然,不能将所有数据输入文件然后 运行 它 - 需要这样做动态变量:

./application /tmp/file | sed '/AB CD 34 43/q'

但我无法做的是传递一个变量而不是十六进制字符串

./application /tmp/file | sed '/`echo -n "$value"`/q'

我不介意我用什么,sed/awk/grep。

我的主要目标是提取十六进制地址之前的所有内容,然后 运行 另一个命令在另一个方向复制相同的内容,如果您愿意的话,我只剩下大部分完整的“框架”。然后我可以根据帧大小对它进行尾部处理,这样它只包含一个完整的帧。

./application /tmp/file | sed "/$value/q"

研究shell中的引用以及单引号和双引号的区别。

要解析 XML 文件,请使用 XML 感知工具,例如 xmlstarlet。不要用正则表达式解析 XML。

不要使用 ` 反引号 - 请改用 $(...)

您的命令替换(反引号)在硬(单)引号 (') 内,因此 shell 不会扩展它。您也不需要 echo,只需要变量本身。对于要扩展的变量,您仍然必须使用软(双)引号 (")。

hex='AB CD 34 43'

./application /tmp/file | sed "/$hex/q"

sed地址中使用shell变量时,请记住它是正则表达式,而不是字符串,并且sed没有像[=19=这样的选项] 的 -F(这样的选项对 sed//{}; 等也没有帮助 - 唯一的选择是事先逃脱)。对于十六进制没问题,因为它只有字母数字和 space 个字符。

此外,如您所说,sed 将打印到包含该模式的 。因此,在同一行上 模式之后的任何文本都将被包括在内。也许这可以满足您的要求,但我将提供一些方法来准确打印(并包括)图案,但不会再多了。

sed

sed -E "/$hex/{s/($hex)(.*)//;q}"

awk

awk -v RS="$hex" '{print([=12=] RS); exit}'

注意:POSIX 表示 RS 应该是单个字符,但许多实现接受正则表达式*

shell

decoded=$(./application /tmp/file)
truncated=${decoded%%"$hex"*}
echo "$truncated"

这会先将所有数据复制到内存中,对于非常大的数据可能会很慢,但是对于小数据会很快,b/c 纯shell。引用 $hex 将其视为字符串而不是模式。

* 来自 https://www.gnu.org/software/gawk/manual/html_node/gawk-split-records.html

RS as a regular expression [is a gawk extension]

mawk has allowed RS to be a regexp for decades. As of October, 2019, BWK awk also supports it.

如果模式 $hex 出现不止一次,这些都会打印到第一次出现的 $hex(包括它),但可以轻松修改以打印到最后一次出现。

最后,当做这样的事情时,请记住 hexdump 实用程序可以使用 printf 之类的格式字符串来控制输出格式。例如 hexdump -ve '1/1 "%02x "' mybinfile; echo 以十六进制转储 space 分隔的字节列表 mybinfile