Remove caracteres se eles não seguirem padrões especificados

2

Eu quero limpar alguns arquivos e fazer com que eles sejam escritos de maneira mais uniforme.

Então, minha entrada se parece com algo assim:

$a$h$l )r
^9 ^5 l
\ urd

O problema é que alguns espaços são "desnecessários" e dificultam a comparação dos arquivos. Por esse motivo, desejo remover todos os espaços, a menos que eles sigam diretamente após um dos seguintes caracteres:

  • $
  • ^
  • T
  • iN (N sendo uma variável, qualquer caractere com 1 byte de comprimento)
  • oN (N sendo uma variável, como acima)
  • s
  • sN (N sendo uma variável, como acima)
  • @
  • !
  • /
  • (
  • )
  • = N (N sendo uma variável, como acima)
  • % N (N sendo uma variável, como acima)

Então, um exemplo de entrada pode ser:

:
$ $ $N
$  $  $a
sa  s l r
*56 l r
o1 o 2
%%x v

Onde a saída desejada seria:

:
$ $ $N
$ $ $a
sa s lr
*56lr
o1 o 2
%%xv

Para o caso %%x v , o espaço é removido porque é o terceiro caractere após o % inicial, em que o segundo % atua como a variável.

Estou usando um sistema operacional GNU / Linux.

    
por user146854 07.01.2016 / 11:41

2 respostas

2

Acho que entendi agora - obrigado .

Com regexp estendido para manipular os opcionais para os caracteres extras em N um pouco mais fácil (note que a entrada de exemplo usada aqui é ligeiramente diferente da sua na pergunta) :

sed -Ee's|([sio=%]..)?([@!T()^$/].)? *||g' \
<<""
:
$ $ $N
$  $  $a
sa  s    l r
*56 l r
o1 o 2
%%xv
:
$ $ $N
$ $ $a
sa s  lr
*56lr
o1 o 2
%%xv

Você precisará de um GNU / BSD / AST sed para usar isso. Um BRE equivalente seria como:

sed 's|\([soi=%]..\)\{0,1\}\([@!T()^$/].\)\{0,1\} *||g'

O truque é fazer com que todas as combinações sejam opcionais, de modo que nenhuma parte de um padrão tenha precedência. Como você está realmente removendo dados - e não inserindo (que teria que ser tratado de forma muito diferente) você não terá problemas com as correspondências para sequências nulas no intervalo entre suas metas de correspondência . Quem se importa quantas seqüências de caracteres nulas são removidas?

A regex de

sed verifica o espaço padrão globalmente e da esquerda para a direita. Se houvesse alguma possibilidade de sobreposição entre as correspondências, isso não funcionaria muito bem, porque não recua em g lobal. Mas há apenas um caso em que posso pensar e é tratado aqui. De qualquer forma, o espaço está sempre do lado direito, e há sempre algum espaço não à esquerda. É possível, no entanto, que N possa ser um dos delims únicos que você nomeou, mas nesse caso o espaço ainda é preservado como deveria ser.

Conforme ele varre, verifica a entrada em relação aos padrões - o primeiro que pode corresponder é o de 3 caracteres, o segundo é o de 2 caracteres e o terceiro é um único - um espaço (embora essa correspondência possa continue por qualquer extensão) .

Quando algum deles for encontrado, sed irá substituir uma das duas primeiras correspondências por si mesma - como a páscoa -, mas a terceira será removida completamente. E de uma só vez.

    
por 07.01.2016 / 11:48
2

Talvez algo como:

perl -pe 's{((?:[ios=\%].|[\$^T\@!/()])+.)| }{$1}g'
    
por 07.01.2016 / 13:28