awk sed if declaração

9

Estou tentando adicionar 0 ao início, SE houver um "." no segundo caractere dessa linha. Eu não consegui combinar esses dois;

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

mostrando o segundo caractere

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

adicionando um zero ao começo.

Deve haver um "se o segundo caractere for um ponto".

arquivo de amostra:

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
    
por G.Ahmet 21.04.2017 / 14:21

5 respostas

12

Podemos usar sed ou awk para resolver completamente o problema.

com sed :

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

Quando & ocorre na parte de substituição do comando de substituição ( s ), ele será expandido para a parte da linha de entrada que corresponde à parte do padrão do comando.

A expressão regular ^.\. significa " corresponde a todas as linhas que começam com ( ^ ) um caractere arbitrário ( . ) seguido por um ponto literal ( \. ) ".

Se a linha for 1.02.2017 23:40:00 , o padrão corresponderá e 1. será substituído por 01. no início da linha.

com awk :

Criando o código parcial awk na pergunta ...

Isto, como dito, imprime o segundo caractere de cada linha de entrada:

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

Podemos usar o fato de que substr($0, 2, 1) retorna o segundo caractere e usa isso como condição:

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

O que entra em { ... } é o código que prefixa $0 , que é o conteúdo da linha atual, com um zero se a condição anterior for verdadeira:

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

Então só precisamos ter certeza de que todas as linhas são impressas:

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

A condição substr($0, 2, 1) == "." pode, é claro, ser alterada para uma expressão regular também (usamos exatamente a mesma expressão que usamos na sed solution):

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

Algumas pessoas que pensam que "menor é sempre melhor" escreveriam isso como

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

(e provavelmente também remove a maioria dos espaços: awk '/^.\./{$0="0"$0}1' file.txt )

    
por 21.04.2017 / 14:39
5

com sed:

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

O padrão /^.\./ procura por qualquer caractere e um ponto literal no início da linha ^ , e se isso corresponder, s ubstitute esse início de linha com um zero, efetivamente adicionando o zero ao início.

O sed expressoin s/.\{0\}/0/ é um tanto estranho, combina zero ou mais cópias de qualquer coisa e substitui com um zero. O padrão, é claro, coincidirá com todas as posições da string, mas como s/// substitui apenas a primeira correspondência, ela funciona como você pretendia. Uma maneira singular de fazer isso, no entanto.

Ou com o awk, um regex semelhante funcionaria para corresponder à linha, mas podemos usar substr :

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

Primeiro, testamos se o segundo caractere é um ponto e, em caso positivo, adicionamos um zero à frente da linha. O último chama a ação padrão de imprimir a linha após quaisquer modificações.

    
por 21.04.2017 / 14:27
4

Você disse awk e sed, mas parece que está tentando formatar uma data e, para isso, eu usaria o comando date . Por exemplo:

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

irá produzir

01.02.2017 23:40:00

O comando sed no meio altera os períodos para barras de entrada em date -d . As opções de formato permitem a saída em praticamente qualquer formato desejado. O %m em particular irá zerar o mês, que é o que parece que você está tentando fazer.

Como Kusalananda aponta:

Ainda mais compacto (data e Bash do GNU): date -f <(tr '.' '/' <dates.in) '+%m.%d.%Y %T'

    
por 21.04.2017 / 21:10
2

Uma estratégia diferente da apresentada nas outras respostas: você pode usar "." como o separador de campo.

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

Você pode apostar isso em:

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

Para sed, há um comando mais curto, apresentado em outra (ótima) resposta.

    
por 22.04.2017 / 08:25
1

Com sed poderia ser

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

Isso usará ^ para ancorar no início da linha e, em seguida, capturar qualquer caractere único em um grupo, seguido por um literal . e, em seguida, por qualquer outra coisa. Se combinarmos que imprimimos um 0 , então nosso primeiro grupo de captura (o caractere no início da linha), então um . , em seguida, nosso segundo grupo de captura (o restante da linha)

    
por 21.04.2017 / 14:26