Numéros de remplissage zéro à 2 chiffres avec sed

19

Contribution:

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

Sortie désirée:

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

Comment puis-je ajouter un 0s'il n'y a qu'un seul chiffre, par exemple 1dans la partie "jour"? J'ai besoin de ce format de date: YYYYMM DD.

LanceBaynes
la source

Réponses:

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
la source
Pouvez-vous expliquer comment cela fonctionne? C'est la première fois que je regarde la \<[0-9]\>construction qui, je pense, est celle responsable de la correspondance des chiffres, mais je ne sais pas comment cette construction est appelée. Merci.
sasuke
2
\ <signifie: début d'un 'mot' ... [0-9] signifie un seul chiffre de 0 à 9 ... \> signifie: fin d'un 'mot' ... mot: un jeton délimité par des espaces (ou commence / fin au début / fin de la ligne, respectivement pour \ <et \>) ... PS. J'ai juste essayé les signes de ponctuation .. ce sont aussi des délimiteurs.
Peter.O
1
Vous pouvez également le faire sans capturer les parenthèses: &dans la chaîne de remplacement, utilisez le LHS correspondant -sed 's/\<[0-9]\>/0&/'
glenn jackman
Oh, je ne savais pas que c'était <>une limite de mot dans la syntaxe des expressions rationnelles du shell. À bien y penser, même `sed 's / \ b [0-9] \ b / 0 & /' fonctionne également. Merci à vous deux. :)
sasuke
@sasuke: <>est une caractéristique de regex étendu (non de la coquille, en tant que telle) ... selon la version et les options que vous utilisez, sedet shellpeuvent aussi bien utiliser soit prolongée ou standards regex ... utilisations standard regex\<\>
Peter. O
18

Une autre solution: awk '{$2 = sprintf("%02d", $2); print}'

glenn jackman
la source
2

Voici une façon (non sed) d'utiliser bash avec regex étendu .
Cette méthode permet à scope de faire un traitement plus complexe de lignes individuelles. (c.-à-d. plus que de simples substitutions d'expression régulière)

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

production:

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
la source
1

Je ferais quelque chose comme ça:

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

Cela saisit les nombres solitaires, les supprime des espaces blancs avec un groupe ' ([0-9]) ', puis les remet en place avec 0 et un espace blanc ' 0\1 '.

L' -Eoption permet des expressions RegEx modernes sur OSX (vous n'avez donc pas à utiliser "\"si souvent), -rfait la même chose sur les systèmes Linux que j'ai testés.

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