【问题标题】:Counting the number of fields stored in a variable计算存储在变量中的字段数
【发布时间】:2012-12-27 05:19:40
【问题描述】:

我正在开发一个基本的文件雕刻器,目前我正忙于计算文件的字节位置。

我发现我需要一段代码来执行以下步骤;

  1. 在变量中找到 $searchQuery
  2. 找到 $searchQuery 后删除字符串的其余部分
  3. 计算变量中现在存在的字段数
  4. 将此变量减去 2 以考虑十六进制偏移量和 $searchQuery 本身
  5. 然后将答案乘以 2 得到正确的字节数

这方面的一个例子是;

  1. 在“00052a0: b4f1 559c ffd8 ffe0 0010 4a46 4946 0001”中找到“ffd8”
  2. 变量更新为“00052a0: b4f1 559c ffd8”
  3. $fieldCount 被赋值为“4”
  4. $fieldCount=((fieldCount-2))
  5. $byteCount=((fieldCount*2))

除了计算变量中的字段数之外,我对如何做所有事情都有一个基本的想法。例如,在找到 $searchQuery 之前,如何计算变量中有多少字段?同样,删除字符串中不必要的部分后,如何计算字段数?

使用 grep 找到 $searchString 后,我不知道如何继续。我当前的代码如下所示;

#!/bin/bash
#***************************************************************
#Name:          fileCarver.sh
#Purpose:       Extracts files hidden within other files
#Author:        
#Date Written:      12/01/2013
#Last Updated:      12/01/2013
#***************************************************************

clear

#Request user input
printf "Please enter the input file name: "
read inputFile
printf "Please enter the search string: "
read searchString

#Search for the required string
searchFunction()
{
    #Search for required string and remove unnecessary characters
    startHexOffset=`xxd $1 | grep $2 | cut -d":" -f 1`
    #Convert the Hex Offset to Decimal
    startDecOffset=$(echo "ibase=16;${startHexOffset^^}" | bc)
}

searchFunction $inputFile $searchString


exit 0

感谢您的帮助!

【问题讨论】:

  • 阅读有关 awk 的信息,它是 FS(字段分隔符)和 NF(字段数)变量。您可以消除所有额外的进程,例如 grepcut。另外,你的问题有点不清楚,你看到这个函数的输出是什么? doc 块说“隐藏在其他文件中的文件”,但您的示例数据似乎不支持这一点。 (请提供示例输出)。祝你好运!
  • 谢谢,我会的!本质上,它将能够通过获取隐藏文件开始的确切字节来提取被不相关数据混淆的文件。例如,它会搜索JPG页眉“ffd8”和页脚“ffd9”,基本上只是将两端的数据全部剪切粘贴到另一个文件中,就可以正常查看图片了。
  • 我添加了echo $fullOffset | awk -F " " "/$searchString/{print NF}"这一行,但它只输出变量中字段的数量。该变量包含00052a0: b4f1 559c ffd8 ffe0 0010 4a46 4946 0001 ..U.......JFIF..
  • 好的,是的。现在,您可以使用{for (i=1;i<=NF;i++){if ($i ~ /$searchString/) printf("fldNum=%d=%s\n", i, $i)} 遍历当前行的所有元素。注意i 可以是一个计数器,就像在c 中一样,但也可以通过$i 引用它的值。这适用于所有在 awk 中保存数字的变量,包括 NF,因此 $NF 将打印该行的最后一个元素,$(NF-3) 将打印该行最后一个字段的第三个(例如)。您可以使用 $(NF-n) 和 n 作为整数值。您可以将 i 的值分配给 startPosendPos,然后遍历该范围 4urfile。祝你好运。
  • 如果我理解您正在尝试正确执行的操作,那么解析 xxd 的输出以查找给定模式是一种非常不灵活的方法。如果您要查找的字节序列没有与 4 字节边界对齐怎么办?如果,当被 xxd 转储时,您的模式被分成几行怎么办?

标签: bash xxd


【解决方案1】:

如果您以更简单的格式将文件转换为十六进制,您可能会发现这更容易。例如,您可以使用命令

hexdump -v -e '/1 "%02x "' $FILE

打印文件,每个字节都转换为三个字符:两个十六进制数字和一个空格。

您可以找到所有ffd8 的实例,前缀为它们的字节偏移:

hexdump -v -e '/1 "%02x "' $FILE | grep -Fbo 'ff d8 '

(字节偏移量需要除以3。)

因此,您可以使用以下方法从ffd8 的第一个实例流式传输整个文件:

tail -c+$((
  $(hexdump -v -e '/1 "%02x "' $FILE | grep -Fbo 'ff d8 ' | head -n1 | cut -f1 -d:)
  / 3 + 1)) $FILE

(假设您用于显示文件的任何内容都知道在到达图像末尾时会停止。但您同样可以找到最后一个结束标记。)

这取决于 GNU grep;标准 Posix grep 缺少 -b 选项。但是,可以使用awk

tail -c+$(
    hexdump -v -e '/1 "%02x\n"' $FILE |
    awk '/d8/&&p=="ff"{print NR-1;exit}{p=$1}'
  ) $FILE

选项说明:

tail    -c+N    file starting at byte number N (first byte is number 1)

hexdump -v      do not compress repeated lines on output
        -e 'FORMAT'  use indicated format for output:
            /1       each format consumes 1 byte
            "%02X "  output two hex digits, including leading 0, using lower case,
                     followed by a space.

grep    -F      pattern is just plain characters, not a regular expression
        -b      print the (0-based) byte offset of the... 
        -o      ... match instead of the line containing the match

cut     -f1     output the first field of each line
        -d:     fields are separated by :

【讨论】:

  • 鉴于 Josh 上面的输入,您的方法考虑了文件页眉/页脚,这些文件页眉/页脚被拆分为多行,这使得它比我已经拥有的更好,但我在理解它时遇到了一些麻烦。我一直在使用的方法搜索标题,在本例中为“ffd8”,并获取该行的偏移量并将其转换为十进制。然后将行首和标题之间的字节数添加到该十进制数上,以形成 dd 进程的起始位置。然后对文件页脚执行相同的操作,但页脚中的字节也包括在内。
  • 现在已知开始和结束位置,计算两者之间的差异并使用 dd 命令提取文件,跳过不需要的数据(开始位置)并提取特定长度的字节(起始位置和结束位置之间的差异)。现在,使用您的方法,我是否正确地认为,在它解析文件中的所有数据以便将其视为用单个空格分隔的单个字节之后,它会删除文件头之前的所有数据,并能够为页脚再次重复此操作,但之后删除所有数据?
  • 谢谢!我让它工作并理解了几乎所有内容。最后你能解释一下“/ 3 + 1”的意义吗?如果我将其更改为“/ 4”,则该行不再有效。
  • @revenant:我同意这有点乱,但第一部分真的很长。将其视为x / 3 + 1(即比 x/3 多一个)。 +1 是因为 tail 将第一个字节视为第一个字节,而 grep 将其报告为第 0 个字节。
  • 好吧,事实证明我必须从中运行它的服务器不喜欢 grep 的 -b 标志,这反过来会破坏整个脚本......有没有“grep -Fbo”的替代品"ff d8" "?
【解决方案2】:

尝试:

echo "00052a0: b4f1 559c ffd8 ffe0 0010 4a46 4946 0001"| awk '
{
for (a=1;a<=NF; a++) {
    if ($a == "ffd8") {
        print substr($0,0,index($0,$a)+length($a))
        break
        }
    }
}'

输出: 00052a0: b4f1 559c ffd8

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-15
    • 1970-01-01
    • 2020-06-30
    • 1970-01-01
    相关资源
    最近更新 更多