Números de preenchimento zero para 2 dígitos com sed


19

Entrada:

201103 1 /mnt/hdd/PUB/SOMETHING
201102 7 /mnt/hdd/PUB/SOMETH ING
201103 11 /mnt/hdd/PUB/SO METHING
201104 3 /mnt/hdd/PUB/SOMET HING
201106 1 /mnt/hdd/PUB/SOMETHI NG

Saída desejada:

201103 01 /mnt/hdd/PUB/SOMETHING
201102 07 /mnt/hdd/PUB/SOMETH ING
201103 11 /mnt/hdd/PUB/SO METHING
201104 03 /mnt/hdd/PUB/SOMET HING
201106 01 /mnt/hdd/PUB/SOMETHI NG

Como posso adicionar um 0se houver apenas um dígito, por exemplo, 1na parte "dia"? Preciso deste formato de data: AAAAMM DD.

Respostas:


13
$ sed 's/\<[0-9]\>/0&/' ./infile
201103 01 /mnt/hdd/PUB/SOMETHING
201102 07 /mnt/hdd/PUB/SOMETH ING
201103 11 /mnt/hdd/PUB/SO METHING
201104 03 /mnt/hdd/PUB/SOMET HING
201106 01 /mnt/hdd/PUB/SOMETHI NG

Você pode explicar como isso funciona? Esta é a primeira vez que olho para o \<[0-9]\>construto, que acho que é o responsável por corresponder os dígitos únicos, mas não tenho certeza do que esse construto é chamado. Obrigado.
sasuke

2
\ <significa: início de uma 'palavra' ... [0-9] significa um único dígito de 0 a 9 ... \> significa: fim de uma 'palavra' ... palavra: um token delimitado por espaços em branco (ou começa / termina no início / fim da linha, para \ <e \> respectivamente) ... PS. Eu apenas tentei sinais de pontuação ... eles também são delimitadores.
Peter.O

1
Você também pode fazer isso sem a captura de parênteses: &na string de substituição usará os LHS combinados -sed 's/\<[0-9]\>/0&/'
Glenn Jackman

Ah, não sabia que havia <>um limite de palavras na sintaxe do shell regex. Venha para pensar sobre isso, mesmo `sed 's / \ b [0-9] \ b / 0 & /' também funciona. Obrigado a ambos. :)
sasuke

@ Sasuke: <>é um recurso do regex estendido (não do shell, como tal) ... dependendo de qual versão e quais opções você usa, sede os shelldois podem usar o regex estendido ou padrão ... o regex padrão usa\<\>
Peter. O


2

Aqui está uma maneira (não-sed) de usar o bash com regex estendido .
Esse método permite que o escopo faça um processamento mais complexo de linhas individuais. (ou seja, mais do que apenas substituições regex)

while IFS= read -r line ; do
    if [[ "$line" =~ ^(.+\ )([0-9]\ .+)$ ]]  
    then echo "${BASH_REMATCH[1]}0${BASH_REMATCH[2]}" 
    else echo "$line"
    fi
done <<EOF
201103 1 /mnt/hdd/PUB/SOMETHING
201102 7 /mnt/hdd/PUB/SOMETH ING
201103 11 /mnt/hdd/PUB/SO METHING
201104 3 /mnt/hdd/PUB/SOMET HING
201106 1 /mnt/hdd/PUB/SOMETHI NG
EOF

saída:

201103 01 /mnt/hdd/PUB/SOMETHING
201102 07 /mnt/hdd/PUB/SOMETH ING
201103 11 /mnt/hdd/PUB/SO METHING
201104 03 /mnt/hdd/PUB/SOMET HING
201106 01 /mnt/hdd/PUB/SOMETHI NG

1

Eu faria algo assim:

sed -E 's/ ([0-9]) / 0\1 /' ./input

Isso pega números solitários, retira-os do espaço em branco com um grupo ' ([0-9]) 'e os coloca novamente com 0 e preenchimento de espaço em branco ' 0\1 '.

A -Eopção permite expressões modernas de RegEx no OSX (para que você não precise usá- "\"lo com tanta frequência), -rfaz o mesmo nos sistemas Linux que testei.


-1
while read a b c
do 
new_format=$(printf "%02d" $b)
echo "$a $new_format $c"
done </tmp/input
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.