Abordagem curta grep
:
echo "ĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄ" | grep -Eo '.{1,3}'
ĄĄĄ
ĄĄĄ
ĄĄĄ
ĄĄĄ
ĄĄĄ
ĄĄĄ
ĄĄĄ
ĄĄ
Para reter apenas sequências de 3 caracteres: ... | grep -Eo '.{3}'
Estou usando fold -w 3
para dividir uma linha em vários 3 caracteres, no entanto, com a implementação GNU, ela não funciona para texto com caracteres de múltiplos bytes.
Como posso alcançar o acima com sed
?
Eu criei sed -r 's/^(.{0,3})(.*)/\n/g'
, mas isso só faz uma substituição:
echo "111222333444555666" | sed -r 's/^(.{0,3})(.*)/\n/g'
111
222333444555666
Exemplos adicionais:
echo "ĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄ" | sed -r 's/^(.{0,3})(.*)/\n/g'
ĄĄĄ
ĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄ
E fold
com o comportamento de corrupção:
echo "ĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄ" | fold -w 3
Ą�
�Ą
Ą�
�Ą
Ą�
Observe que o problema não é com o conjunto de caracteres Unicode, mas com caracteres codificados em 2 ou mais bytes (assim como caracteres com largura diferente de uma célula).
UTF-8 é uma codificação de Unicode onde os caracteres U + 0080 a U + 10FFFFF são codificados em 2 ou mais bytes. Os caracteres Unicode U + 0000 a U + 007F são os mesmos que em ASCII e em UTF-8 são codificados em um único byte (o mesmo que em ASCII) e não são um problema aqui.
Existem outras codificações do conjunto de caracteres Unicode (como iso8859-1, byte único, mas limitado aos caracteres U + 0000 a U + 00FF ou GB18030, multi-byte), e há outros conjuntos de caracteres não-Unicode com codificações de múltiplos bytes.
Você pode dizer qual codificação de caracteres é usada em sua localidade com o comando locale charmap
.
A implementação GNU de fold
atualmente só funciona corretamente com caracteres de byte único. O fold
da maioria dos outros sistemas não tem esse problema. Muitos podem até manipular caracteres com largura de exibição zero ou dupla.
A implementação de fold
do busybox suportou o UTF-8 (não outros charmaps multi-byte) desde 2010.
No FreeBSD ou no Solaris:
$ echo $'a\u0301bcde' | fold -w3
ábc
de
com o busybox fold:
$ echo $'a\u0301bcde' | busybox fold -w3
áb
cde
com dobra GNU:
$ echo $'a\u0301bcde' | fold -w3
á
bcd
e
U + 0301 é um acento agudo combinando. Ele tem uma largura nula e em UTF-8 é codificado em 2 bytes (0xcc 0x81). Então, esse á
( $'a\u0301'
) é um cluster grafema de largura 1 feito de 2 caracteres codificados em 3 bytes, daí os 3 comportamentos diferentes, o mais correto dos quais é o FreeBSD / Solaris 'aqui.
Usando sed:
$ echo "ĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄ" | sed 's/.../&\n/g'
ĄĄĄ
ĄĄĄ
ĄĄĄ
ĄĄĄ
ĄĄĄ
ĄĄĄ
ĄĄĄ
ĄĄ
Ou solução (ões) mais geral (mais fácil de definir o número de caracteres):
sed 's/.\{3\}/&\n/g' # Using BRE (basic) syntax
sed -E 's/.{3}/&\n/g' # Using ERE (extended) syntax.
Encontrou uma solução:
echo "ĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄ" | sed -r 's/(.{0,3}){1}/&\n/g'
ĄĄĄ
ĄĄĄ
ĄĄĄ
ĄĄĄ
Só porque ...
$ echo "ĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄĄ" | gawk '{$1=$1} 1' FPAT=".{,3}" OFS="\n"
ĄĄĄ
ĄĄĄ
ĄĄĄ
ĄĄĄ
ĄĄĄ
ĄĄĄ
ĄĄĄ
ĄĄ
Aqui está uma solução POSIX:
awk '{gsub(/.{5}/, "&\n")} 1'
Curiosamente, a solução Awk tem mais desempenho que dobra.