我习惯fold -w 3
将一行分成多个 3 个字符长的行,但是对于 GNU 实现,它似乎不适用于具有多字节字符的文本。
我怎样才能实现上述目标sed
?
我已经想出了,sed -r 's/^(.{0,3})(.*)/\1\n\2/g'
但这只能进行一次替换:
echo "111222333444555666" | sed -r 's/^(.{0,3})(.*)/\1\n\2/g'
111
222333444555666
其他示例:
echo "ĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄ" | sed -r 's/^(.{0,3})(.*)/\1\n\2/g'
ĄĄĄ
ĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄ
以及fold
它的腐败行为:
echo "ĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄ" | fold -w 3
Ą�
�Ą
Ą�
�Ą
Ą�
答案1
短的grep
方法:
echo "ĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄ" | grep -Eo '.{1,3}'
ĄĄĄ
ĄĄĄ
ĄĄĄ
ĄĄĄ
ĄĄĄ
ĄĄĄ
ĄĄĄ
ĄĄ
仅保留 3 个字符的序列:... | grep -Eo '.{3}'
答案2
请注意,问题不在于 Unicode 字符集,而在于使用 2 个或更多字节编码的字符(以及宽度不是一个单元格的字符)。
UTF-8 是 Unicode 的一种编码,其中 U+0080 至 U+10FFFFF 的字符被编码在 2 个或更多字节上。Unicode 字符 U+0000 至 U+007F 与 ASCII 中的字符相同,并且在 UTF-8 中被编码在单个字节上(与 ASCII 中的字符相同),因此在这里不是问题。
Unicode 字符集还有其他编码(例如 iso8859-1,单字节但仅限于字符 U+0000 到 U+00FF,或 GB18030,多字节),还有其他多字节的非 Unicode 字符集编码。
您可以使用该命令了解您的语言环境中使用的字符编码locale charmap
。
目前, GNU 实现fold
只能正确处理单字节字符。大多数fold
其他系统不存在这个问题。许多甚至可以处理零或双倍显示宽度的字符。
自 2010 年起,busybox 实现fold
就支持 UTF-8(但不支持其他多字节字符映射)。
在 FreeBSD 或 Solaris 上:
$ echo $'a\u0301bcde' | fold -w3 ábc de
与 busybox 折叠:
$ echo $'a\u0301bcde' | busybox fold -w3 áb cde
使用 GNU 折叠:
$ echo $'a\u0301bcde' | fold -w3 á bcd e
U+0301 是一种组合锐音。它具有空宽度,并且在 UTF-8 中以 2 个字节 (0xcc 0x81) 进行编码。因此,á
( $'a\u0301'
) 是一个宽度为 1 的字素簇,由 3 个字节编码的 2 个字符组成,因此有 3 种不同的行为,其中最正确的是 FreeBSD/Solaris 的行为。
grep
使用带有 PCRE 支持、UTF-8 语言环境和 UTF-8 输入构建的GNU :
grep -Po '\X{1,3}'
在输入的每一行上输出o
1 到 3(尽可能多)的所有序列 eX
倾向于字素簇,对于上述将标记与单宽字符组合的情况,可能会给您更好的结果。
如果存在双角字符或不与单角字符组合的零字符,或者存在 TAB、CR、BS 等控制字符,则无济于事。
答案3
使用 sed:
$ echo "ĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄ" | sed 's/.../&\n/g'
ĄĄĄ
ĄĄĄ
ĄĄĄ
ĄĄĄ
ĄĄĄ
ĄĄĄ
ĄĄĄ
ĄĄ
或者更通用的解决方案(更容易定义字符数):
sed 's/.\{3\}/&\n/g' # Using BRE (basic) syntax
sed -E 's/.{3}/&\n/g' # Using ERE (extended) syntax.
答案4
只因为...
$ echo "ĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄ" | gawk '{$1=$1} 1' FPAT=".{,3}" OFS="\n"
ĄĄĄ
ĄĄĄ
ĄĄĄ
ĄĄĄ
ĄĄĄ
ĄĄĄ
ĄĄĄ
ĄĄ