Ordem de prioridade de correspondência de padrões do sed / regexes reversa

5

Considere este comando:

echo "string.with.dots" | sed 's/\(.*\)\.\(.*\)/\n/'

(Combina em um primeiro grupo de captura qualquer caractere até o último . e em um segundo grupo de captura qualquer caractere depois dele.)

Esta saída:

string.with
dots

Razoavelmente (acho) Eu pensei que usar âncoras na combinação correta teria conseguido reverter esse comportamento (isto é, a correspondência teria sido string para o primeiro grupo de captura e with.dots para o segundo grupo de captura), mas:

echo "string.with.dots" | sed 's/^\(.*\)\.\(.*\)/\n/'
echo "string.with.dots" | sed 's/^\(.*\)\.\(.*\)$/\n/'
echo "string.with.dots" | sed 's/\(.*\)\.\(.*\)$/\n/'

Toda a saída:

string.with
dots

Eu não sei como a correspondência de padrões é implementada, mas parece que sempre privilegia os padrões mais perto do início da string, em vez daqueles que estão mais próximos do final da string (apesar de estarem presentes ^ ou faltando $ ).

Como esse comportamento pode ser alterado (ou seja, não como escrever uma solução codificada neste exemplo, mas como reverter a ordem de prioridade de correspondência de padrões em sed ou em expressões regulares em geral ), se possível?

    
por kos 06.04.2015 / 22:36

3 respostas

1

Adicione dois rev e troque e :

echo "string.with.dots" | rev | sed 's/\(.*\)\.\(.*\)/\n/' | rev

Saída:

string
with.dots
    
por Cyrus 06.04.2015 / 23:03
3

Para conseguir o que você quer, tente isto:

sed -r 's/^([^.]*)\.(.*)/\n/'

Teste:

$ echo "string.with.dots" | sed -r 's/^([^.]*)\.(.*)/\n/'
string
with.dots

sed corresponderá com avidez, portanto, enquanto você estiver usando sed 's/\(.*\)\.\(.*\)/\n/' , ele corresponderá rapidamente ao último . como o primeiro grupo capturado e depois o restante após o . como segundo.

Na minha expressão sed , para impedir que sed seja ganancioso, tenho que procurar algumas alternativas. Eu combinei desde o início com um . como o primeiro grupo ( [^.]* ) e depois depois do primeiro jogo como o segundo.

Agora, se você quiser todas as partes em torno de . em linhas separadas:

$ echo "string.with.dots" | sed -r 's/^([^.]*)\.([^.]*)\.(.*)/\n\n/'
string
with
dots
    
por heemayl 06.04.2015 / 22:43
1

Gostaria de saber se você pode usar a expansão de parâmetros

$ s="string.with.dots"
$ echo "${s%%.*}"; echo "${s#*.}"
string
with.dots
$ echo "${s%.*}"; echo "${s##*.}"
string.with
dots
    
por glenn jackman 06.04.2015 / 23:26

Tags