Números de relleno de cero a 2 dígitos con 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

Salida deseada:

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

¿Cómo puedo agregar un 0si solo hay un dígito, por ejemplo, 1en la parte "día"? Necesito este formato de fecha: AAAAMM DD.

LanceBaynes
fuente

Respuestas:

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
SiegeX
fuente
¿Puedes explicar cómo funciona esto? Esta es la primera vez que miro el \<[0-9]\>constructo, que creo que es el responsable de hacer coincidir los dígitos individuales, pero no estoy seguro de cómo se llama este constructo. Gracias.
Sasuke
2
\ <significa: inicio de una 'palabra' ... [0-9] significa un solo dígito de 0 a 9 ... \> significa: final de una 'palabra' ... palabra: una ficha que está delimitada por espacios en blanco (o comienza / termina al inicio / final de la línea, para \ <y \> respectivamente) ... PS. Acabo de probar los signos de puntuación ... también son delimitadores.
Peter.O
1
También puede hacer esto sin capturar paréntesis: &en la cadena de reemplazo usará el LHS coincidente -sed 's/\<[0-9]\>/0&/'
glenn jackman
Oh, no sabía que <>es un límite de palabras en la sintaxis de expresiones regulares de shell. Ahora que lo pienso, incluso 'sed' s / \ b [0-9] \ b / 0 & / 'también funciona. Gracias a los dos. :)
sasuke
@sasuke: <>es una característica de la expresión regular extendida (no del shell, como tal) ... dependiendo de la versión y las opciones que use, sedy shellambas pueden usar la expresión regular extendida o estándar ... usa la expresión regular estándar\<\>
Peter. O
18

Otra solución: awk '{$2 = sprintf("%02d", $2); print}'

Glenn Jackman
fuente
2

Aquí hay una forma (no sed) de usar bash con expresiones regulares extendidas .
Este método permite que el alcance realice un procesamiento más complejo de líneas individuales. (es decir, más que simples sustituciones de expresiones regulares)

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

salida:

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
Peter.O
fuente
1

Haría algo como esto:

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

Esto toma números solitarios, los despoja de espacios en blanco con un grupo ' ([0-9]) ' , luego los vuelve a colocar con 0 y relleno de espacios en blanco ' 0\1 '.

La -Eopción permite expresiones RegEx modernas en OSX (para que no tenga que usarlas con "\"tanta frecuencia), -rhace lo mismo en los sistemas Linux que he probado.

Eric
fuente
-1
while read a b c
do 
new_format=$(printf "%02d" $b)
echo "$a $new_format $c"
done </tmp/input
Mohamed ELKHALIFI
fuente