使用 sed 替换随机位置的字符?

使用 sed 替换随机位置的字符?

我正在尝试替换文件中随机位置的字符。我的文件看起来像:

aab  
babab  
abab  

我正在尝试用随机字符替换“c”。所以输出可能如下所示:

aab  
bcbab  
abab 

我尝试删除所有换行符并保存在文件 new_string.txt 中,然后使用 sed 但它不起作用。

这是我尝试过的代码:

rand1="$(shuf -i 0-$tot_len -n 1)"
sed "s/^\(.\{"${rand1}"\}\)./\1G/" new_string.txt

我不断收到错误:

sed: -e expression #1, char 25: Invalid content of \{\}

答案1

变量中不需要大括号,并且变量也应该被引用。使用:

sed "s/^\(.\{$rand1\}\)./\1G/" new_string.txt

更新:如评论中所述:

原始代码很好,但是 的整数$rand1对于 来说太大了sed。我发现最大值可以是32767GNU 的sed,即sed仍然只需要 16 位整数。

您可以通过以下方式获取系统正则表达式库的限制(尽管 GNUsed通常使用内置版本):

$ getconf RE_DUP_MAX
32767

POSIX 要求该限制至少为_POSIX_RE_DUP_MAX(255),这是您可以期望可移植的最大值(某些系统(如 Solaris 或 OS/X)的限制如此之低)。

答案2

在 GNU 系统上,要随机替换一个字符(换行符除外),您可以这样做:

file=myfile.txt
offset=$(grep -bo . < "$file" | cut -d: -f1 | shuf -n1)
[ -z "$offset" ] || # file doesn't have non-newline characters
  printf c | dd bs=1 seek="$offset" of="$file" conv=notrunc status=none

(对于旧版本的 GNU dd(8.20 之前的版本),替换status=none2> /dev/null)。

grep -bo . < "$file"将为您提供文件中每个非换行符的字节数偏移量。例如,一个以 UTF-8 编码的文件包含:

$3
£1
€2

这给了我们:

$ grep -bo . < "$file"
0:$
1:3
3:£
5:1
7:€
10:2

对于cut -d: -f1,我们保留第一个冒号之前的部分。然后,我们使用 随机选择这些偏移量之一shuf -n1

这假设替换字符与被替换字符具有相同的大小。例如,将上面的 £(2 个字节)替换为 c(1 个字节)将使文件后跟c一个无效字符。

为了解决这个问题,我们不能再就地覆盖文件,因为我们需要移动数据。

我们需要类似的东西:

perl -C -0777 -pi -e "substr \$_, $offset, 1, 'c'" -- "$file"

反而。与-Cperl尊重构成的区域设置特点-0777 -p打开吸食的内容$file被吞入的模式$_(参见运行 perl -ne '...' * 的安全隐患尽管出于该构造的安全考虑)。-pi为您提供就地编辑,$_在代码运行后写回文件。然后我们调用substr将给定偏移量处的 1 个字符替换为c

答案3

\n使用新的 GNU sed,即使没有ewline remove也可以做到这一点

sed -z "s/./@/$(($RANDOM%$(wc -m < file.txt)))" file.txt

答案4

尝试这个:

sed 's/^\(.\{'"${rand1}"'\}\)./\1G/'  new_string.txt

相关内容