我想用tr
替换数字0-5
和替换A
数字。6-9
B
我尝试使用sed
这样做:
sed 's/[0-4]/</; s/[6-9]/>/'
但它只能工作一次,所以例如,如果我写它,123
它只会带有A23
而不是AAA
.
答案1
对于sed
,您需要添加g
,以便它将替换每行中出现的所有内容:
sed 's/[0-4]/A/g;s/[5-9]/B/g'
使用tr
,您可以链接两个tr
s:
tr '0-4' A | tr '6-9' B
或显式提供字符转换:
tr 0123456789 AAAAABBBBB
甚至:
tr 0-45-9 AAAAABBBBB
(但我发现后者的可读性较差,因为 1-1 映射不是立即可见的)。
重复的B
s 可以缩写(tr
根据需要重复最后一个字符),并且可以合并范围:
tr 0123456789 AAAAAB
tr 0-9 AAAAAB
对于更复杂的替换,拆分命令可以帮助使其目的更加明显:
tr 0123456789 \
AAAAABBBBB
或者,利用引用范围与这种情况下的扩展长度相匹配的事实:
tr '0-4''5-9' \
AAAAABBBBB
我假设范围分割是 0-4 和 5-9,以均匀分割,如示例的第一个命令中所示sed
。可以根据需要调整范围。
答案2
/g
使用末尾的量词对所有字符进行全局替换。如果没有它,替换将在第一个匹配的字符处结束,并将不是随后继续进行。
另一种用于sed
音译字符的方法(类似于tr
)在 GNU 和 POSIX 中均可用
sed 'y/123456789/AAAAABBBB/'
答案3
POSIXly:
tr 0123456789 AAAAAABBBB
tr 0123456789 '[A*6][B*4]'
tr 0123456789 '[A*6][B*]'
sed 's/[012345]/A/g; s/[6789]/B/g'
sed 'y/0123456789/AAAAAABBBB/'
一些注意事项:
tr 012345 A
不是 POSIX,因为第二组的大小与第一组的大小不同。tr 0-5 AAAAAA
仅保证在 POSIX/C 语言环境中工作。sed 's/[0-5]/A/g'
对于非 POSIX 语言环境中的where[0-5]
可以匹配比 012345 更多的内容也是如此。
请注意,截至 2020 年,与 的 GNU 实现tr
相反, 的 GNU 实现sed
不支持多字节(尽管我相信存在一些补丁来添加某种程度的支持),因此这些tr
方法不能在 GNU 上使用使用 GB18030 等字符集的语言环境中的系统,其中大多数字符的编码包含十进制数字的编码。
例如:
$ printf '%s\n' "$LANG"
zh_CN.gb18030
$ locale charmap
GB18030
$ locale title
Chinese locale for Peoples Republic of China
$ tr --version
tr (GNU coreutils) 8.30
[...]
$ sed --version
sed (GNU sed) 4.7
[...]
$ echo '£12' | tr 0123456789 '[A*6][B*4]'
丄凙AA
$ echo '£12' | sed 'y/0123456789/AAAAAABBBB/'
£AA
这是因为£
(英镑符号)被编码为字节 0x81 0x30 0x84 0x35,其中 0x30 也是 的编码0
,0x35 也是 的编码5
:
$ echo '£12' | LC_ALL=C od -vtx1 -tc
0000000 81 30 84 35 31 32 0a
201 0 204 5 1 2 \n
0000007
$ echo '£12' | tr 0123456789 '[A*6][B*5]' | LC_ALL=C od -vtx1 -tc
0000000 81 41 84 41 41 41 0a
201 A 204 A A A \n
0000007
答案4
假设范围是 0-4 和 5-9:
tr 0-9 AAAAAB
或者
sed y_0123456789_AAAAABBBBB_