Estou tendo problemas para reduzir minha sintaxe sed para adicionar um número variável de zeros à esquerda em um esquema organizacional numérico. As cordas nas quais estou operando aparecem como
1.1.1.1,Some Text Here
alavancando a sintaxe sed
sed -r ":r;s/\b[0-9]{1,$((1))}\b/0&/g;tr"
Eu sou capaz de obter a resposta
01.01.01.01,Some Text Here
No entanto, o que estou procurando é algo que preencha com zero até 2 dígitos nos campos 2 e 3 e 3 dígitos no campo 4, para que todos os itens tenham um comprimento padrão em [0-9]. [0-9] { 2}. [0-9] {2}. [0-9] {3}
1.01.01.001,Some Text Here
Durante toda a minha vida, não consigo imaginar nem mesmo como modificar o limite para incluir os parâmetros necessários para ajustar apenas os números após um período. Eu acho que tem algo a ver com o uso do \ b que eu entendo corresponde a zero caracteres em um limite de palavras, mas não entendo por que minhas tentativas de adicionar um ponto à correspondência falham da seguinte maneira:
sed -r ":r;s/\.\b[0-9]{1,$((1))}\b/0&/g;tr"
sed -r ":r;s/\b\.[0-9]{1,$((1))}\b/0&/g;tr"
Both cause the statement to hang
sed -r ":r;s/\b[0-9]\.{1,$((1))}\b/0&/g;tr"
sed -r ":r;s/\b[0-9]{1,$((1))}\.\b/0&/g;tr"
sed -r ":r;s/\b[0-9]{1,$((1))}\b\./0&/g;tr"
cause the statement to output:
1.01.01.1,Some Text Here
Além disso, espero ter problemas adicionais se a declaração contiver texto como:
1.1.1.1,Some Number 1 Here
É uma conclusão precipitada que eu realmente preciso aprender o sed e todas as suas complexidades. Estou trabalhando nisso, mas espero que essa declaração em particular continue a me causar problemas por um tempo. Qualquer ajuda seria muito apreciada.
Edição: Eu descobri uma maneira ... Esta declaração parece fazer o que estou procurando, mas deve haver uma maneira mais elegante de fazer isso.
sed -r ':r;s/\b[0-9]{1,1}\.\b/0&/;tr;:i;s/\b[0-9]{1,2},\b/0&/;ti;s/.//'
Além disso, sintaticamente, isso causará problemas se um formato de número semelhante aparecer no texto ... semelhante a:
1.1.1.1,Some Text Referring to Document XXX Heading 1.2.3
Nesse caso, resultará em:
1.01.01.001,Some Text Referring to Document XXX Heading 01.02.03
Resolvido Obrigado a todos pela ajuda aqui. Inicialmente resolvi o problema com a resposta que aceitei abaixo. Eu senti que mudou a solução para Python como parte de uma solução maior, aproveitando o tipo abaixo:
def getPaddedKey(line):
keyparts = line[0].split(".")
keyparts = map(lambda x: x.rjust(5, '0'), keyparts)
return '.'.join(keyparts)
s=sorted(reader, key=getPaddedKey)
fonte
sed -r ':r;s/\b[0-9]{1,1}\.\b/0&/;tr;:i;s/\b[0-9]{1,2},\b/0&/;ti;s/.//'
No entanto, eu adoraria saber se existe uma abordagem mais elegante.printf
(ou umaprintf
chamada no Awk) pode ser mais direto.Respostas:
Uso:
leading_zero.sh input.txt
Explicação:
input.txt
output.txt
fonte
perl
versão não remove as barras invertidas.bash pode lidar com isso. No entanto, será muito mais lento que o perl:
fonte
printf
, a ferramenta sensata. (O Awkprintf
também foi e foi melhor projetado do quebash
para o processamento de texto.) Veja também Por que o uso de um loop de shell para processar o texto é considerado uma má prática?Você não pediu especificamente uma
perl
solução, mas aqui está uma de qualquer maneira. Pessoalmente, acho que isso é um pouco mais fácil de ler, especialmente quando dividido em várias linhas.Primeiro, aqui está o one-liner:
Seus resultados:
E aqui está o
perl
script dividido e comentado (a-n
flag coloca umwhile read; do ... done
loop implícito em torno do código):fonte
awk
iria trabalhar muito - mesmo princípio usandoprintf
Aqui está uma abordagem possível:
sed -E 's/([0-9]*\.)/0\1/g;s/.//;s/([0-9]*,)/00\1/'
Exemplos
Também trabalhe com esta sequência:
... e esta sequência:
fonte
Explicação:
O método usado aqui é examinar as vizinhanças dos números e agir com base nisso. Assim, o 2º e o 3º números veem um ponto nos dois lados, enquanto o 4º numérico vê um ponto à esquerda e uma vírgula à direita.
O $ 1 é definido quando o regex segue o caminho de 2º ou 3º nums e, portanto, o preenchimento de precisão é 2. OTOH, para o 4º num, o preenchimento é 3.
% cat file.txt
Resultados:
fonte