Tentando excluir um caractere final de palavra com o sed regex

0

Eu sou novo em regex e sed e estou tentando criar o que eu achava que seria um regex direto: quero remover a letra final da palavra se for um 'o'.

  • Cadeia de entrada: Olá, Olá
  • Saída esperada: Hell Hell

A boa notícia: posso remover o 'o' quando estiver no final da string:

$ echo 'Hello Hello' |sed 's/\(.*\)o//g'
Hello Hell
$ echo 'Hello Hello' |sed 's/\(.*\)o$//g'
Hello Hell

A má notícia: não consigo removê-lo das palavras anteriormente na string. Eu tentei isso com todos os símbolos âncora que eu posso pensar. O resultado é que nenhum dos 'o's finais da palavra é removido:

$ echo 'Hello Hello' |sed 's/\(.*\)o\b//g'
Hello Hello
$ echo 'Hello Hello' |sed 's/\(.*\)o\>//g'
Hello Hello
$ echo 'Hello Hello' |sed 's/\(.*\)o\W//g'
Hello Hello
$ echo 'Hello Hello' |sed 's/\(.*\)o\s//g'
Hello Hello

Você pode me ajudar a recuperar minha sanidade dizendo-me o que estou fazendo de errado?

Atualização: tenho a impressão de que minha máquina produz resultados diferentes dos de outras pessoas. Eu estou usando a janela do terminal no meu Macbook. Se alguém puder lançar alguma luz sobre isso, por favor me diga.

    
por Triplesmeg 20.11.2017 / 20:59

4 respostas

1

echo 'Hello Hello' | sed 's/o$//'

parece mais útil para mim do que o seu

echo 'Hello Hello' | sed 's/\(.*\)o$//g'

Na sua pergunta diz-se que a saída de

echo 'Hello Hello' | sed 's/\(.*\)o\b//g'

foi Hello Hello , mas para mim é Hello Hell . Você pode corrigir isso para

echo 'Hello Hello' | sed 's/\([^o]*\)o\b//g'

mas

echo 'Hello Hello' | sed 's/o\b//g'

parece melhor para mim.

    
por 20.11.2017 / 21:25
1

Remover o no final das palavras é remover um o entre um caractere de palavra e um caractere que não seja de palavra (ou o EOL), portanto:

sed -r 's/(\w)o(\W|$)//g'
    
por 20.11.2017 / 22:56
1

Eu estou querendo saber se de alguma forma space não é o seu termo delimitador. Tente algo como o seguinte:

$ echo hello hello | sed -e 's/o / /g;s/o$//'
hell hell

O problema com este exemplo é que você também terá que fazer o mesmo para . e , e qualquer outro delimitador de palavras. Corresponde o seguido por outro caractere específico com [] like o[ \.,] . Por algum motivo, isso não funciona para EOL $ , portanto, adicione outra string de pesquisa com ; . Exemplo:

$ echo hello hello, hello. toot hello | sed -e 's/o\([ \.,]\)//g;s/o$//'
hell hell, hell. toot hell
$ echo $SHELL
/bin/bash
$ sed --version
sed (GNU sed) 4.4
$ set | grep IFS
IFS=$' \t\n'
    
por 27.11.2017 / 19:15
0

I have tried this with all the anchor symbols I can think of.

Não são as âncoras, mas o fato de você ter um jogo ganancioso com o asterisco. A expressão \(.*\)o corresponde a o mais que uma string , por isso ele vai comer tudo até o último o . Pode coincidir com os anteriores o também.

Mas, então, capturar algo e devolvê-lo de volta é inútil, basta remover o \(.*\) e o completamente.

Então, isso (pelo menos no GNU sed) remove o no final das palavras:

sed 's/o\>//g' 
sed 's/o\b//g' 

Isso, é claro, apenas no final da string:

sed 's/o$//g' 

E isso removerá um o , juntamente com um caractere não relacionado a palavras (por exemplo, o espaço após Hello ):

sed 's/o\W//g' 

Se o seu sed não suportar \< / \> ou \b , você terá que fazer outra coisa. Isso corresponderia a o seguido por um caractere não alfanumérico ou o fim da linha:

$ echo "jello, jello" | sed -E -e 's/o([^[:alnum:]]|$)//g'
jell, jell

Isso funciona, por exemplo no sed que vem com o OS X / macOS.

As expressões regulares de Perl suportam a adição de um ponto de interrogação a * ou + para torná-las não-vorazes. Em seguida, eles corresponderiam à sequência mais mais curta possível:

echo "jello, jello" | perl -pe 's/(.*?)o/$1/g'
jell, jell
    
por 20.11.2017 / 21:36