Substitui caracteres em um índice específico contados a partir de trás

1

Eu quero mudar alguns caracteres em uma string que eu crio. Eu faço um filelisting e de cada arquivo eu preciso acrescentar a informação "stat". Por exemplo, o nome do arquivo "K181_111126.CATProduct" resulta em "K181_111126.CATProduct.2011-11-28 13:33:33.722342000 +0100" . Os últimos 16 caracteres que eu não preciso, eu resolvi com:

find . -type f -exec stat -c%n.%y {} \; | sed 's/.\{16\}$//'

Resultado: "K181_111126.CATProduct.2011-11-28 13:33:33" Meu problema é que eu preciso alterar o espaço (nono caractere por trás) entre data e hora com um "-" e todos os ":" no tempo (13:33:33) com um ponto "."
Todas as strings têm tamanhos diferentes, então só posso contar por trás.

    
por Walter Reis 13.07.2017 / 16:04

3 respostas

2

Substitua o espaço e os dois pontos ao mesmo tempo usando um regex ligeiramente maior.

find . -type f -exec stat -c%n.%y {} \; |
sed 's/ \(..\):\(..\):\(..\).\{16\}$/-../'

O espaço antes do 24º caractere do final é correspondido, então combinamos e capturamos os próximos 2 caracteres, uma vírgula, os próximos 2, uma comra e outros 2; então, os últimos 16 são correspondidos e substituídos por nada. A primeira expressão capturada pode ser recuperada usando uma referência de referência (a segunda com , etc). Em outras palavras, os dois dígitos após o espaço são "substituídos" por eles mesmos, ou seja, efetivamente retidos, seguidos por um ponto, os dois seguintes, etc.

    
por 13.07.2017 / 17:30
1

Acho que é isso que você está procurando:

$ s='K181_111126.CATProduct.2011-11-28 13:33:33.722342000 +0100'
$ echo "$s" | rev | sed -E 's/.{16}//; s/:/./; s/:/./; s/ /-/' | rev
K181_111126.CATProduct.2011-11-28-13.33.33

Isso usa rev para reverter o caractere da linha de entrada, de modo que seja mais fácil processar e, finalmente, rev novamente

  • s/.{16}// exclui os primeiros 16 caracteres
  • s/:/./; s/:/./ muda primeiro dois : para .
  • s/ /-/ altera o primeiro espaço para -
por 13.07.2017 / 16:21
0
find ... |
sed -Ee '
  s/.{16}$//
  :a;s/:([^:[:blank:]]*)$/./;ta
  s/[[:blank:]]([^[:blank:]]+)$/-/
'

Onde depois de excluir os 16 caracteres finais, da mesma forma que você fez, configuramos um loop para converter progressivamente o : - > . e quando terminar, altere o último caractere mais em branco para um traço. Isso é necessário, pois o nome do arquivo também pode incluir caracteres em branco e precisamos ignorá-los.

    
por 14.07.2017 / 10:08

Tags