awk sed if, déclaration

9

J'essaye d'ajouter 0 au début, SI il y a un "." au 2e caractère de cette ligne. Je ne pouvais pas combiner ces deux;

awk '{ print substr( $0, 2, 1 ) }' file.txt 

montrant le deuxième caractère

sed -ie "s/.\{0\}/0/" file.txt

en ajoutant un zéro au début.

Il devrait y avoir un "si le deuxième caractère est un point".

exemple de fichier:

1.02.2017 23:40:00
10.02.2017 23:40:00

final:

01.02.2017 23:40:00
10.02.2017 23:40:00
G.Ahmet
la source

Réponses:

12

Nous pouvons utiliser l'un sedou l'autre awkpour résoudre complètement le problème.


Avec sed:

$ sed 's/^.\./0&/' file.txt

Lorsque &survient dans la partie de remplacement de la commande de substitution ( s), il sera étendu à la partie de la ligne d'entrée qui correspond à la partie de modèle de la commande.

L'expression régulière ^.\.signifie " correspondre à toutes les lignes commençant par ( ^) un caractère arbitraire ( .) suivi d'un point littéral ( \.) ".

Si la ligne est 1.02.2017 23:40:00, le motif correspondra et 1.sera remplacé par 01.au début de la ligne.


Avec awk:

S'appuyant sur le awkcode partiel de la question ...

Comme indiqué, cela imprimera le deuxième caractère de chaque ligne d'entrée:

$ awk '{ print substr($0, 2, 1) }' file.txt

Nous pouvons utiliser le fait que substr($0, 2, 1)renvoie le deuxième caractère et l'utiliser comme condition:

$ awk 'substr($0, 2, 1) == "." { ... }' file.txt

Ce qui se passe { ... }est un code qui précède $0, qui est le contenu de la ligne actuelle, avec un zéro si la condition précédente est vraie:

$ awk 'substr($0, 2, 1) == "." { $0 = "0" $0 }' file.txt

Ensuite, nous devons juste nous assurer que toutes les lignes sont imprimées:

$ awk 'substr($0, 2, 1) == "." { $0 = "0" $0 } { print }' file.txt

La condition substr($0, 2, 1) == "."peut bien sûr également être changée en une expression régulière (nous utilisons exactement la même expression que celle utilisée dans la sedsolution):

$ awk '/^.\./ { $0 = "0" $0 } { print }' file.txt

Certaines personnes qui pensent que "plus court est toujours mieux" écriraient cela comme

$ awk '/^.\./ { $0 = "0" $0 } 1' file.txt

(et probablement aussi supprimer la plupart des espaces: awk '/^.\./{$0="0"$0}1' file.txt)

Kusalananda
la source
1
+1 Votre dernier exemple AWK ou votre exemple sed sont les bonnes façons de le faire. Notez, pour plus de clarté, que ce ne serait que l'un ou l'autre.
pause jusqu'à nouvel ordre.
À mon avis , l'approche « correcte » ( ce qui ne fonctionne pas du violon avec des espaces et qui est un poids plus léger de toute façon) est votre version finale, sed 's/^.\./0&/' file.txt. Je pense que vous devriez mettre cela au début de cette réponse. Pourtant, +1.
Wildcard
1
@Wildcard Nous visons à plaire.
Kusalananda
5

Avec sed:

sed -e "/^.\./s/^/0/" file.txt 

Le motif /^.\./recherche n'importe quel caractère et un point littéral au début de la ligne ^, et si cela correspond, sremplacez ce début de ligne par un zéro, en ajoutant effectivement le zéro au début.

L'expressoin sed s/.\{0\}/0/est quelque peu étrange, elle correspond à zéro ou plusieurs copies de quoi que ce soit et remplace par un zéro. Le motif correspondra bien sûr à chaque position de la chaîne, mais comme il s///ne remplace que la première correspondance, il fonctionne comme vous le souhaitiez. Une façon pittoresque de le faire, cependant.


Ou avec awk, une expression rationnelle similaire fonctionnerait pour correspondre à la ligne, mais nous pouvons utiliser substr:

awk 'substr($0, 2, 1) == "." {$0 = "0" $0} 1' file.txt 

Nous testons d'abord si le deuxième caractère est un point, puis ajoutons un zéro au début de la ligne si c'est le cas. La dernière invoque l'action par défaut d'imprimer la ligne après toute modification.

ilkkachu
la source
4

Vous avez dit awk et sed, mais il semble que vous essayez de formater une date et pour cela j'utiliserais la datecommande. Par exemple:

echo '1.2.2017 23:40:00' | sed 's/\./\//g' | xargs -0 date '+%m.%d.%Y %T' -d

affichera

01.02.2017 23:40:00

La sedcommande au milieu change les périodes en barres obliques pour la saisie date -d. Les options de format permettent une sortie dans presque tous les formats souhaités. En %mparticulier, le zéro sera complété le mois, ce qui semble être ce que vous essayez de faire.

Comme le souligne Kusalananda:

Encore plus compact (date GNU et Bash): date -f <(tr '.' '/' <dates.in) '+%m.%d.%Y %T'

bmb
la source
2
Belle prise! Encore plus compact (date GNU et Bash):date -f <(tr '.' '/' <dates.in) '+%m.%d.%Y %T'
Kusalananda
Chaque fois que j'ai Slashes dans mes habitudes, mais pas de tuyaux: s|\.|/|g. Sinon, comme indiqué ci-dessus: belle prise, +1
Alex Stragies
2

Une stratégie différente de celle présentée dans les autres réponses: vous pouvez utiliser "." comme séparateur de champ.

awk -F. '$1 < 10 {printf "0"} {print}' /tmp/in.txt

Vous pouvez jouer au golf pour:

awk -F. '$1<10{printf "0"}1' /tmp/in.txt

Pour sed, il y a une commande plus courte, présentée dans une autre (excellente) réponse.

Alex Stragies
la source
1
Alternative: awk -F. '{print ($1<10?0$0:$0)}' file
George Vasiliou
1

Avec sed ça pourrait être

sed 's/^\(.\)\.\(.*\)/0\1.\2/'

Cela servira ^à ancrer au début de la ligne, puis à capturer n'importe quel caractère unique dans un groupe, suivi d'un littéral ., puis de toute autre chose. Si nous correspondons à ce que nous imprimons a 0, alors notre premier groupe de capture (le caractère au début de la ligne), puis a .puis notre deuxième groupe de capture (le reste de la ligne)

Eric Renouf
la source
Il n'est pas du tout nécessaire de faire cette capture. &est votre ami. Voir l'exemple sed de Kusalananda.
pause jusqu'à nouvel ordre.
@DennisWilliamson n'est pas nécessaire, mais étant donné qu'il existe déjà d'autres exemples, cela montre une autre caractéristique sedqui pourrait être utile dans d'autres situations, pas seulement ce problème spécifique
Eric Renouf