O que há de errado com essa expressão sed?

6
$ echo "104_Fri" | sed 's/^\([0-9]+\)_\([A-Za-z]+\)$/;/'
104_Fri

Eu gostaria de combinar os dígitos no início e as letras no final - cada um como um grupo. Depois eu quero mostrar o primeiro grupo, um ponto-e-vírgula e depois o segundo grupo.

Espero que esta expressão produza:

104;Fri

Por que isso não funciona?

    
por Raffael 28.07.2014 / 11:39

5 respostas

7

Você também deve sair com o símbolo + :

$ echo "104_Fri" | sed 's/^\([0-9]\+\)_\([A-Za-z]\+\)$/;/'
104;Fri
    
por 28.07.2014 / 11:41
11

Barra invertida no + :

$ echo "104_Fri" | sed 's/^\([0-9]\+\)_\([A-Za-z]\+\)$/;/'
104;Fri

Observe que + não é um metacaractere de expressão regular básica e por isso não tem comportamento portátil em sed , mesmo quando é invertida.

Você deve usar sed -r ou sed -E para ativar expressões regulares estendidas em vez disso, em que você não precisa fazer backslash em nenhum desses caracteres. Essas opções também não são padrão, mas pelo menos você receberá um erro se elas não forem suportadas, em vez de falhas misteriosas. As opções são suportadas pelo GNU sed e todos os principais derivados do BSD (FreeBSD , OpenBSD , NetBSD , OS X ), mas não em muitas versões comerciais do Unix.

Se você precisar de expressões regulares estendidas verdadeiramente portáveis, use awk , que sempre as usa .

    
por 28.07.2014 / 11:54
6

Adicione a opção -r ;-) para regexps estendidos, e a necessidade de \ de conteúdo ativo diminui.

$ echo "104_Fri" | sed -re 's/^([0-9]+)_([A-Za-z]+)$/;/'
104;Fri

Como o Q está escrito, (sem dados de segundo plano), a divisão de tarefas pode ser feita de várias outras maneiras mais simples:

$ echo "104_Fri" | tr '_' ';'
104;Fri

$ echo "104_Fri" | sed  's/_/;/'
104;Fri

... para citar dois.

    
por 28.07.2014 / 13:51
5

Você também pode alternar endereços. Você acaba usando muito menos barras invertidas assim.

sed -n '/._./{/^[0-9]*.[A-Za-z]*$/s/_/;/p;}'

sed -n '/[^0-9].*_.*[^A-Za-z]/d;/._./s/_/;/p'
    
por 28.07.2014 / 12:39
1

Eu sugiro usar o Perl, já que ele vem pré-instalado na maioria dos sistemas Unix:

$ echo '104_Fri' | perl -p -e 's/^([0-9]+)_([A-Za-z]+)$/$1;$2/'

Você pode simplificar ainda mais:

$ echo '104_Fri' | perl -p -e 's/^(\d+)_([a-z]+)$/$1;$2/i'

Observação: Se sua entrada for realmente tão simples quanto na pergunta, um simples tr será o seguinte:

$ echo '104_Fri' | tr '_' ';'

Ou com o Perl:

$ echo '104_Fri' | perl -p -e 's/_/;/'
    
por 28.07.2014 / 17:06

Tags