2

我正在寻找以特定字节偏移量替换字符。

提供的内容如下: 简单 ASCII 文本的输入文件。Bash shell 脚本中的一个数组,数组的每个元素都是一个数字字节偏移值。

目标:获取输入文件,并在每个字节偏移处,用星号替换那里的字符。

所以基本上我想到的想法是以某种方式逐个字节地遍历文件,如果当前读取的字节偏移量与偏移量数组中的元素值匹配,则将该字节替换为星号。

这篇文章似乎表明dd命令将是此操作的一个很好的候选者,但我不明白如何在输入文件上多次执行替换。

输入文件如下所示:

00000
00000
00000

偏移量数组如下所示:

offsetsArray=("2" "8" "9" "15")

输出文件的所需格式如下所示:

0*000
0**00
00*00

非常感谢您提供的任何帮助。谢谢!

4

3 回答 3

4

请查看我关于换行偏移的评论。假设这是正确的(注意我已经改变了你的偏移数组),那么我认为这应该适合你:

#!/bin/bash

read -r -d ''
offsetsArray=("2" "8" "9" "15")
txt="${REPLY}"
for i in "${offsetsArray[@]}"; do
    txt="${txt:0:$i-1}*${txt:$i}"
done
printf "%s" "$txt"

解释:

  • read -d ''一次将整个输入(重定向文件)读取到$REPLY变量中。如果您有大文件,这可能会使您内存不足。
  • 然后我们遍历 offsets 数组,一次一个元素。我们使用每个索引从字符串的开头i抓取 i-1字符,然后插入一个*字符,然后从 offset 添加剩余的字节i。这是通过bash 参数扩展完成的。请注意,虽然您的偏移量是从一开始的,但字符串使用从零开始的索引。

正在使用:

$ ./replacechars.sh < input.txt
0*000
0**00
00*00
$ 

警告:

这并不是一个非常有效的解决方案,因为它会导致包含整个文件的字符串针对每个偏移量都被复制。如果您有大文件和/或大量偏移量,那么这将运行缓慢。如果您需要更快的东西,那么另一种允许修改字符串中单个字符的语言会更好。

于 2014-04-19T21:07:26.150 回答
3

的用法dd在当时可能有点混乱,但并不难:

outfile="test.txt"

# create some test data
echo -n 0123456789abcde > "$outfile"

offsetsArray=("2" "7" "8" "13")
for offset in "${offsetsArray[@]}"; do
    dd bs=1 count=1 seek="$offset" conv=notrunc of="$outfile" <<< '*'
done

cat "$outfile"

对于此示例,重要的是使用conv=notrunc,否则 dd 会将文件截断为它所寻找的块的长度。bs=1指定您要使用大小为 1 的块,并seek指定要写入count块的偏移量。

以上产生01*3456**9abc*e

于 2014-04-19T21:16:17.657 回答
2

与@DigitalTrauma 的卓越解决方案具有相同的偏移考虑,这里有一个基于 GNU awk 的替代方案。这假设您的文件不包含空字节

(IFS=','; awk -F '' -v RS=$'\0' -v OFS=''  -v offsets="${offsetsArray[*]}" \
'BEGIN{split(offsets, o, ",")};{for (k in o)  $o[k]="*"; print}' file)

0*000
0**00
00*00
于 2014-04-19T21:12:45.760 回答