O [[: space:]] funciona para padrões sed em todas as distribuições do Linux?

2

Usar [[:space:]] parece um pouco não-elegante e, francamente, o Microsoft-ish para sed corresponder aos padrões. Eu estava tentando extrair "Last" de "First Last" e qualquer um dos seguintes funcionou:

echo "First Last" | sed s/First //
echo "First Last" | sed s/First\s//

O que funcionou é

echo "First Last" | sed s/First[[:space:]]//

Eu queria saber:

  1. Existe uma notação mais minimalista para corresponder a um espaço em branco em sed ?
  2. O [[:space:]] funciona em todas as distribuições do Linux?
por amphibient 06.02.2014 / 18:33

2 respostas

5

Sim, [:space:] deve ser reconhecido por todas as edições sed , faz parte de Expressões regulares básicas conforme definido por POSIX .

A notação \s é das Extensões Regulares Compatíveis com Perl que são implementadas em muitos programas (grep com -P , por exemplo) e idiomas (perl, php, java, javascript, python ...). Nenhuma dessas sintaxes de regex tem algo a ver com a Microsoft!

Se você quiser a sintaxe PCRE, por que não usar o Perl? Ambos funcionam:

echo "First Last" | perl -pe 's/First\s//'
echo "First Last" | perl -pe 's/First *//'

O sinalizador -p significa "imprimir todas as linhas" depois de executar qualquer script passado com -e .

    
por 06.02.2014 / 18:55
0

A sintaxe do BRE é não-elegante , onde algumas outras variações são elegantes porque o BRE foi projetado para ser facilmente abstraído . BRE é simplesmente analisado - um programador que implementa sua própria gramática baseada em BRE subconjunto não precisa se preocupar se a sequência de caracteres de correspondência \s for indicar uma barra invertida \ seguida por s ou a classe de caractere [[:space:]] - porque a primeira é sempre verdadeira. É por esse mesmo motivo que as expressões de sintaxe são aquelas que são \( escape \) em oposição a ( literal chars ) e por que \ barras invertidas perdem seu significado especial em [ char classes ] .

Se você acha que essa explicação é um pouco exagerada, primeiro considere como isso realmente é feito ...

dot_whole_words()(
    s=[:space:] b=[:blank:] w=_[:alnum:] z1=\{0,1\}
    sed "G;s/[$b]*\([$w]*[^$w$s][^$s]*\)$z1\([$w]*\)[$s]/./g"
)

Essa pequena função shell selecionará apenas palavras inteiras de uma linha de entrada e separará aquelas encontradas com um ou mais . dots na saída.

echo 1 2 3 four five si.x se\$Ven eight 9nine\! |
dot_whole_words
.1.2.3.four.five...eight.

Ele aborrece todas as palavras que têm um único ponto de pontuação anexado, como é evidenciado por 9nine! não ser encontrado. Isso também pode ser tratado com alguma abstração adicional.

whole_words_imp()(
        s=[:space:] b=[:blank:] w=_[:alnum:] p=[:punct:]
        z1=\{0,1\} p1=\{1,\} pn=[$p]$z1
        cs=\\([$w]* ce=\\)
        wd=$cs$ce    ce=$ce$z1
        nwd=$cs[$p][^$s]$p1$ce
        nwd=$nwd$cs[^$w$s$p][^$s]*$ce
        sed -ne:n -e'$!{N;/\n$/!bn' -e\} -eG \
                  -e"s/[$b]*$pn$nwd$wd$pn\([$s]\)$p1//g" \
                  -e"/[^$s]/s/[$s]$p1/ /gp"
)

Agora, essa versão lerá um parágrafo de entrada por vez e, quando encontrar uma linha em branco, reduzirá todas as entradas lidas até agora apenas para palavras , como pode ser composto por qualquer número de [$w] caracteres, e que pode ser conduzido ou arrastado por no máximo um sinal de pontuação em ambos os lados.

Por exemplo:

printf %s\n 1 2 3 \
       four five   \
       si.x se\$Ven\
       eight 9nine\! |
whole_words_imp
1 2 3 four five eight 9nine

E assim, como espero que você possa ver, o BRE é tão elegante como você faz.

    
por 16.07.2015 / 07:31