Como pesquisar, substituir e acrescentar um padrão ao final de cada linha

2

Eu tenho a seguinte lista de itens:

bigBone
fishMarket
dogCollar
...

Eu preciso gerar um mapeamento de dois caracteres como este:

bigBone -> bb
fishMarket -> fm
dogCollar -> dc
...

Como posso criar o mapeamento acima usando sed ?

Eu tentei algo como:

sed -i -r 's/^([a-z]{1})[a-z]+([A-Z]{1})[a-zA-Z]+/ -> \L/' file

Eu vi esta pergunta , mas não tenho certeza de como incorporar o conceito aqui. Obrigado.

    
por Question Overflow 06.05.2014 / 09:15

6 respostas

4

Se eu entendi corretamente, então você quer manter toda a linha e apenas acrescentar algo:

sed -r 's/^([a-z]{1})([a-z]+)([A-Z]{1})([a-zA-Z]+)$/ -> \L/' file

editar :

devnull teve que me lembrar que há uma solução fácil para isso:

sed -r 's/^([a-z]{1})[a-z]+([A-Z]{1})[a-zA-Z]+/& -> \L/' file

Ou, um pouco mais elegante (do que a minha primeira tentativa):

sed -r '
h
s/^([a-z]{1})[a-z]+([A-Z]{1})[a-zA-Z]+/ -> \L/
t append
b
: append
H
g
s/\n//' file
    
por 06.05.2014 / 09:24
4

Usando o GNU sed:

sed -r 's/(.)[^[:upper:]]*(.).*/& -> \L/' inputfile

Para sua entrada, produziria:

bigBone -> bb
fishMarket -> fm
dogCollar -> dc
    
por 06.05.2014 / 09:52
3

Para generalizar para fooBarBaz -> fbb , abCdEfGh -> aceg , com GNU sed :

sed -r 's/(.)(.*)/\n -> \L/;:1
        s/\n([^[:upper:]]*([[:upper:]]))(.*)/\n\L/;t1;s/\n//'

POSIX sed não tem \L . Portanto, portável, você teria que recorrer ao uso de y e inserir manualmente todos os caracteres que deseja converter em minúsculas. Algo como:

LC_ALL=C sed '/^\([[:alpha:]]\).*/{
h;s///;y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/;G
s/\(.\).\(.\)\(.*\)/\
 -> /;:1
/.*\n[^A-Z]*\([A-Z]\).*/{h;s///
y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/;G
s/^\(.\)\n\(.*\)\n\([^A-Z]*[A-Z]\)\(.*\)/\
/;t1
}
s/\n//;}'
    
por 06.05.2014 / 11:14
2

Aqui está um script compatível com POSIX. Não sabia que POSIX sed deixa o comportamento de s///[n]g não especificado, mas com certeza , não é um comportamento bem definido. De qualquer forma, é fácil de lidar sem isso - eu simplesmente não gosto de usar muitas referências para trás se ele puder ser ajudado, normalmente.

sed '/^[a-z]*[A-Z].*$/{ h
    s/\(.\)[^A-Z]*//g
    y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/
    H ; g 
    s/\n/ -> /
    }' <<\DATA
bigBone
fishMarket
dogCollar
DATA

#OUTPUT
bigBone -> bb
fishMarket -> fm
dogCollar -> dc
    
por 06.05.2014 / 09:35
1

Esta resposta é semelhante à do @ devnull's,

$ sed 's/\(.\).*\([A-Z]\).*/& -> \L/g' file
bigBone -> bb
fishMarket -> fm
dogCollar -> dc
    
por 06.05.2014 / 15:23
1

Se você puder usar perl , tente:

$ perl -MList::Util=first -F// -aple '$_ .= " -> ".$F[0].lc(first{ord() < 97} @F)' file
bigBone -> bb
fishMarket -> fm
dogCollar -> dc
    
por 06.05.2014 / 15:57