Eu tenho um arquivo CSV com milhares de linhas como estas
1664;4;5;35;37;43;5;6
1663;21;23;32;40;49;8;11
1662;16;17;34;35;44;5;10
1661;2;9;23;32;40;6;7
1660;23;25;30;44;47;9;12
1659;3;5;9;32;43;6;10
1658;4;6;10;13;34;3;5
1657;8;9;33;35;40;3;6
1656;15;20;31;44;48;1;3
1655;25;27;35;40;45;7;11
1654;7;32;33;34;38;6;9
1653;5;7;11;27;37;6;12
1652;7;31;33;35;36;7;10
1651;4;12;34;35;45;1;9
1650;5;8;29;35;48;5;6
1649;2;11;28;42;48;4;9
1648;2;11;12;19;38;4;8
Você pode ver que os números entre 1 e 9 são de um único dígito.
Como posso usar sed
ou algo para converter esses números em dois dígitos, precedendo um zero para eles, como
01 02 03 04 05 06 07 08 09
em vez de
1 2 3 4 5 6 7 8 9
Desde já, obrigado.
Aqui está uma solução usando
awk
:Isso primeiro definirá o separador de campos de entrada e saída como
;
. Em seguida, ele irá iterar sobre todos os campos e normalizar a largura do campo para pelo menos dois dígitos com preenchimento de zero à esquerda usandosprintf()
(o que efetivamente não alterará o conteúdo do campo se já for um número de dois dígitos).A parte externa aparentemente perdida
1
dos blocos de ação instruiawk
a imprimir a linha atual incluindo todas as alterações.Observe que,
awk
por padrão, o arquivo não será modificado, mas apenas impresso emstdout
, então você iráawk
versão que suporte a-i inplace
extensão:Observe também que este caso específico é adaptado ao seu exemplo de entrada, que compreende apenas números de um ou dois dígitos. Para o caso mais geral de preenchimento de
n
dígitos, você usariaDada a sua amostra de entrada, parece
Deveria fazer isso.
Isso precede a
0
todos os dígitos precedidos e seguidos por uma palavrab
oundary. Substitua\d
por[1-9]
se quiser0
ficar sozinho, como sugere o texto da sua pergunta.O mesmo com a implementação GNU do
sed
Com versões recentes do
mlr
(miller), você também pode fazer:Para formatar todos os campos numéricos como números inteiros preenchidos com 0 até um comprimento de 2.
Isso deixará os números em campos não numéricos (como em
"foo 1 and 2";x-2
) intocados, mas observe que também reformatará números não inteiros (1e0
,10e-1
,1.123
,0x1
seriam todos alterados para,01
por exemplo).Para preencher apenas os campos que consistem em apenas um dígito decimal (entre aspas ou não):
Você pode usar
sed
para escolher uma "palavra" que tenha um único dígito e prefixá-la com zero:Saída
Neste caso não importa se o arquivo realmente é CSV (campos separados por vírgula, "
,
"), ou se possui campos separados por ponto e vírgula (";
"), ou mesmo campos separados por espaço em branco.Se o seu
sed
suporte,-i
você pode editar o arquivo "no local", mas observe que, em comum com a maioria dos outros utilitários, o efeito "no local" é implementado nos bastidores como "gravar em um arquivo temporário e, em seguida, substituir o arquivo original por aquele temporário":Usando Miller com inferência de tipo (
-A
) e gerando valores inteiros com preenchimento de zero e largura mínima de campo de 2:Observe que, com base em sua amostra de entrada, presumi que os dados são, na verdade, numerados de índice em vez de CSV.
Usando Raku (anteriormente conhecido como Perl_6)
O código acima usa
Text::CSV
o módulo do Raku. Na primeira instrução o arquivo CSV é lido, configurando osep
parâmetro para aceitar;
ponto e vírgula como separadores de coluna. Na segunda instrução, asprintf
diretiva"%.2d"
define cada coluna com uma largura mínima de 2, preenchida com zeros. Na saída;
os pontos e vírgulas são restaurados como separadores de colunas, caso contrário será utilizado o padrão (vírgula).A resposta acima vale para arquivos CSV com cada coluna sendo inteira. Até agora, inteiros não assinados são
NYI
(ainda não implementados). Pode ser preferível usar a forma de stringsprintf
, tomando o cuidado de adicionar0
ao código de formatação, que direciona o preenchimento com zeros em vez de espaços em branco. Segunda declaração alternativa abaixo:@a = @a>>.map( {sprintf "%02s", $_ } );
Entrada de amostra:
Exemplo de saída (qualquer exemplo acima):
Entrada/Saída: Você pode redirecionar a saída para um novo arquivo obtendo o código excelente de @AdminBee ou @roiama (ou ambos). Se você deseja direcionar entrada/saída de dentro do próprio código, os valores dinâmicos
$*IN
e podem ser substituídos por PATHs (veja o segundo URL abaixo para obter detalhes).$*OUT
https://docs.raku.org/routine/sprintf
https://github.com/Tux/CSV
https://raku.org
Super bruto.
Super lento.
Pode ser útil.
Usando qualquer editor de texto - substitua todas as ocorrências de ",1," por ",01," etc.
Dígitos únicos no final da linha precisam, por exemplo,
substituir todas as ocorrências de ",3[identificador EOL]" por ",03[identificador EOL]"