No POSIX sed, o ponto (ponto) corresponde a uma nova linha em um espaço de padrão de múltiplas linhas?

6

No GNU sed, funciona. Por exemplo, isso combina duas linhas em branco em um espaço de padrão multilinha (criado com N )

/^\n$/

Isso é padrão?

    
por user148873 25.12.2015 / 22:27

1 resposta

7

Sim.

Basic/Extended Regular Expressions

A period ., when used outside a [ bracket expression ], is a[n] [BE]RE that shall match any character in the supported character set except NUL.

Muitas implementações regexp POSIX (como grep ou sed ) não têm dificuldade em corresponder a uma nova linha porque o . não corresponde, mas sim porque o delimitador de entrada é uma nova linha - e assim eles simplesmente não têm nenhuma nova linha na string digitalizada para corresponder.

Um POSIX grep nunca pode corresponder a uma nova linha - é sinônimo com a cadeia nula para grep . sed é semelhante, exceto pelo fato de que sed pode realizar edições ou extrair entrada extra de acordo com comandos com script, e os resultados podem incluir novas linhas no padrão de espaço, mesmo que nunca ocorram de outra forma. Nesse caso, porém, o . corresponderá ao \n ewline.

Uma coisa que não pode ser feita com praticamente qualquer implementação POSIX que eu saiba é a correspondência do complemento ^ de uma nova linha. Isso ocorre porque uma barra invertida \ representa a própria expressão de [ ] e, portanto, a saída \n significa apenas \ e n . Como geralmente também é um erro de sintaxe incluir uma nova linha literal em uma expressão regular (embora pax seja uma exceção da qual eu sei) , você não pode fazer [^ <newline> ] portably.

Uma implementação sensata deve lidar com "[$(printf '--7')]" , mas isso limita a correspondência em cenários multibyte.

Há também: "\(\([^[:space:]]*[[:blank:]$(printf '\r\v\f')]*\)*\)" , mas isso é um pouco pesado.

O que você pode fazer portável, porém, é trocar temporariamente todas as novas linhas no espaço padrão com algum outro caracter (e vice-versa, é claro) , e então combinar o complemento daquele outro caractere. / p>

Por exemplo:

printf %s\n "a a" "b b" "c c" |
sed -e 'H;1h;$!d;x;l' -e '# slurps input to last line - usually a bad idea'   \
    -e 'y/ \n/\n /;l' -e '# transliterates spaces and newlines at once'       \
    -e 's/[^ ]*//2;l' -e '# substitutes away 2cd sequence of not spaces'      \
    -e 'y/ \n/\n /;l' -e '# transliterates spaces and newlines again'
a a\nb b\nc c$
a\na b\nb c\nc$
a\na  c\nc$
a a\n\nc c$
a a

c c

Existem 4% de comandosl ook nesse pequeno script - um para cada vez que o espaço de padrão é alterado após a última linha ser encontrada. Cada um dos comandos l ook corresponde a uma das quatro primeiras linhas de saída acima, que são facilmente marcadas pelo caractere $ final.

As últimas três linhas são os resultados de todas as edições impressas por sed para stdout por padrão. A segunda linha está totalmente vazia, porque sed substituiu a segunda seqüência do complemento do caractere de espaço, que correspondia a todos os caracteres no espaço padrão, exceto novas linhas de entrada naquele momento, e assim a segunda sequência era toda a segunda linha, menos seu delimitador de nova linha à direita.

Importante, isso funciona porque o ponto (ou a sua mais restritiva expressão [ ] alternative) corresponde a uma nova linha.

    
por 25.12.2015 / 22:37