Substitua todas as ocorrências de \ exceto \ N

3

Eu tenho um arquivo como este:

1,2,subjects,\mat\hs,unix\,\Nato,\N,123,\N

Eu quero substituir todas as ocorrências de \ com #, exceto para \ N, de forma que a saída seja assim:

1,2,subjects,#mat#hs,unix#,#Nato,\N,123,\N

Eu estou tentando escrever um comando sed que se parece com -

sed -e 's@\([^N])@#/g' filename

mas isso falhará para todos os valores sempre que houver um \ N no início do exemplo. \Nato no exemplo acima.

Alguém poderia me ajudar a descobrir um comando sed (regex) para minha exigência.

    
por user2118349 28.07.2013 / 21:47

4 respostas

2

Eu não sou tão versado em sed . Mas isso pode ser feito facilmente em perl usando a expressão regex:

perl -pe 's/\(?!N\b)/#/g' your_file_here

Isso imprimirá o arquivo modificado para stdout. Para fazer as substituições no lugar, você pode fazer:

perl -pi -e 's/\(?!N\b)/#/g' your_file_here

Basicamente, isso substitui qualquer barra invertida não seguida por N\b (o caractere N em um limite de palavra) com # .

Editar

Se tiver certeza absoluta de que suas entradas são delimitadas por vírgula, você pode fazer isso para cobrir o caso em que \N esteja no final de uma palavra (como em SOLEM\N no exemplo fornecido):

perl -pe ' s/\/#/g; s/(\A|,)\s*#N\s*(\Z|,)/$1\N$2/g;' your_file_here

Ele simplesmente substitui qualquer barra invertida por um hash mark e procura por #N encontrado entre duas vírgulas, entre o início da string e uma vírgula ou entre uma vírgula e o final da string.

    
por 28.07.2013 / 22:09
2
$ echo '1,2,subjects,\mat\hs,unix\,\Nato,\N,123,\N' \
  | sed -r -e 's@\([^N]|N[^,])@#@g'
1,2,subjects,#mat#hs,unix#,#Nato,\N,123,\N

Editar para \ N como parte de um caso de palavras: (ver comentários)

$ echo '1,2,subjects,\mat\hs,unix\,\SOLEM\N,\N,123,\N' \
  | sed -r -e 's@,\N$@,:SINGLE_N_PLACEHOLDER:@g' \
           -e 's@^\N,@:SINGLE_N_PLACEHOLDER:,@g' \
           -e 's@,\N,@,:SINGLE_N_PLACEHOLDER:,@g' \
           -e 's@\@#@g' \
           -e 's@:SINGLE_N_PLACEHOLDER:@\N@g'
1,2,subjects,#mat#hs,unix#,#SOLEM#N,\N,123,\N

Isso é feio e não confiável (a string de espaço reservado precisa ser única, vai parar de funcionar se esse padrão aparecer no texto), mas não encontrei uma maneira de fazer asserções de uso sed da maneira como o PCRE / Perl as suporta.

Você pode torná-lo mais curto assim:

$ echo '1,2,subjects,\mat\hs,unix\,\SOLEM\N,\N,123,\N' \
  | sed -r -e 's@\@#@g' \
           -e 's@(,|^)#N(,|$)@\N@g'
1,2,subjects,#mat#hs,unix#,#SOLEM#N,\N,123,\N

Mas, nesse caso, um único #N é o marcador que ainda não deve aparecer na string.

    
por 28.07.2013 / 22:08
2
sed -e 's@\\([^N]\|\(N[a-zA-Z]\|$\)\)@#@g' your_file_here

Explicando: Substitua todos os \ seguidos por

  • qualquer coisa que não seja N ,
  • ou N seguido por qualquer letra em [a-zA-Z] (estenda isso se necessário)
  • fim da linha

com # e o restante do padrão correspondente.

    
por 29.07.2013 / 21:48
1
$ echo '1,2,subjects,\mat\hs,unix\,\Nato,\N,123,\N'   | 
         sed -r -e 's/\N/XELI/g' | 
         sed -e 's/\/#/g' | 
         sed -e 's/XELI/\N/g'
1,2,subjects,#mat#hs,unix#,\Nato,\N,123,\N

Acho mais legível dividi-lo:

  • substitua \ N por algum caracter não ocorrente,
  • , em seguida, substitua / por #
  • e substitua o / N de volta
por 28.07.2013 / 22:37