我正在尝试替换文件中随机位置的字符。我的文件看起来像:
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
。我发现最大值可以是32767
GNU 的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=none
为2> /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"
反而。与-C
,perl
尊重构成的区域设置特点。-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