我正在尝试确定二进制文件中的记录数。二进制文件的大小由 确定wc -c
。分隔符未知。记录大小是固定的。每条记录的确切大小未知我想确定记录数
答案1
尝试这个:
script.sh
:
#!/bin/bash
# read filename to var f from $1
f="$1"
# quit if file not found.
[ -f "$f" ] || { >&2 echo "File not found." ; exit 2; }
# total length of file (-1 to not count newline at the end of a file)
n=$(($(wc -c < "$f")-1))
# loop potential length of records, end at half total length of file.
for i in $(seq 1 $(awk -v n=$n 'BEGIN{print int((n/2)+0.5)-1}')); do
# now read all delimiters regarding record length from a file
# (see https://unix.stackexchange.com/a/276957/236063)
# and `sort -u` to get only individual ones
c=$(for ((j=i;j<n;j=j+i+1)); do printf '%s\n' $(dd ibs=1 skip=$j count=1 < "$f" 2>/dev/null); done | sort -u)
# if we have exactly one individual delimiter, we're done and can print length of record and the delimiter and exit.
if [ $(echo "$c" | wc -l) -eq 1 ]; then
printf 'l=%s d=%s\n' "$i" "$c"
exit 0
fi
done
>&2 echo "No delimiter found".
exit 1
内容file
:
abc,def,ghi
输出:
$ ./script.sh file
l=3 d=,
退出代码:
0 success, found delimiter and record length
1 no delimiter found
10 file not found
注意:我认为还需要做一些工作来解决一些问题,特别是关于换行符......
答案2
不知道记录(和分隔符)的确切大小使得这个问题无法用简单而优雅的解决方案来解决。
主要警告: 这可能是一种绝望的情况,因为可能根本没有分隔符(如果写入文件的软件知道记录大小,则不需要用分隔符分隔记录)或者整个文件可能是一条记录。此外,在某些情况下,在记录内被视为分隔符的字符之前可能有“转义字符”(不太可能使用固定的记录大小,但它会使情况变得更糟,分析起来),但“这取决于”。此外,二进制文件格式在实际记录开始之前可以有一个“标头”块,您需要知道它的大小才能工作。
但希望渺茫。由于记录的固定大小长度是确定的,那么 -假设没有标题- 文件的大小(通过 获得wc -c
)必须是记录大小和记录数的乘积。
我们可以尝试暴力方法:
- 查找文件的大小
wc -c
(让其命名fileSize
) - 求 的因数
fileSize
。 - 找到所有因素的组合,这样您就可以获得适合文件的所有可能数量的记录。
- 检查字符结尾可能的记录大小。如果您发现假设的数字具有以相同字符结尾的记录,您可能会认为这是分隔符。
这并不是 100% 完美,但应该有助于进一步研究记录和文件。
例子:
文件内容:
abcxdefxabnxccdxdfaxaafx
文件大小:24字节
因数:
factors 24
: 2 2 2 3可能的组合:
- 2 x 12(两条记录,每条12字节)
- 3×8
- 4×6
- 6×4
- 8×3
- 12×2
对于上面的每一种可能性,我们都有分隔符:
x
x
- (不同的,所以不考虑这种情况)
x
- (不同的)
- (不同的)
我们可能会猜测这
x
是分隔符,最小可能的记录大小是 4 个字符,这符合情况。
这只是一个例子。你应该尝试不同的假设,如果文件很大,你可以使用另一种方法,比如找出两个相同字符之间的距离。