SED challenge, agregando String contendo chaves

3

Estou tentando usar o sed para agregar um padrão de sequência específico em um texto por horas, mas não consigo encontrar a solução. Espero que vocês saibam como fazer isso!?

  • O assunto do texto para minha meta consiste apenas em caracteres de string (sem invisível \ t presente).
  • Eu quero encontrar partes da string que contenham (TAB), mas pelo menos duas ao lado uma da outra e no máximo 8 adjacentes uma à outra e substituí-las por uma única entrada (TAB).

  • A pesquisa deve ser executada dentro de um arquivo Shell, contendo um script bash

Exemplo:

#/!bin/bash

text="Column One(TAB)(TAB)(TAB)Column Two(TAB)(TAB)Column three(TAB)Column4"

modText='echo $text | sed 's/([(]\{1\}TAB[)]\{1\})\{2,8\}/(TAB)/g''
  • Eu tentei várias versões do comando sed, o acima é apenas um deles. Minha ideia original era modText = 'echo $ text | sed 's / \ (TAB \) \ {1 \}) \ {2,8 \} / (TAB) / g' '

Seria ótimo se você pudesse me ajudar. Tenho a sensação de que a solução não está tão longe, mas simplesmente não tenho mais idéias e minha pesquisa não fez isso: -S

Exemplo de texto

"Coluna Um (TAB) (TAB) (TAB) Coluna Dois (TAB) (TAB) Coluna três (TAB) Coluna4"

Meus critérios de pesquisa seriam correspondidos pelos dois primeiros grupos (TAB), ocorrendo entre "Coluna Um" e "Coluna três".

O resultado deve ser assim:

"Coluna Um (TAB) Coluna Dois (TAB) Coluna três (TAB) Coluna4"

    
por Silverlight 19.07.2016 / 08:24

2 respostas

4

Não sei se entendi como a cláusula "maximum 8" deve se aplicar, mas a abordagem ingênua seria algo assim:

sed 's/\((TAB)\)\{2,8\}/(TAB)/g'
    
por 19.07.2016 / 08:32
3

Se você quer dizer que a substituição não deve ser feita se houver mais de 8 (TAB) s adjacentes, você poderia fazer:

sed '
   s/_/_u/g; # escape _
   s/|/_p/g; # escape |
   s/(TAB)/|/g; # use a single character in place of (TAB)
   s/.*/<&>/; # add leading and trailing non-| character
   s/\([^|]\)|\{2,8\}\([^|]\)/|/; # replace up to 8 | provided
                                      # they are not preceded nor followed
                                      # by |
   s/.\(.*\).//; # undo wrapping
   s/|/(TAB)/g;    # undo replacement
   s/_p/|/g;s/_u/_/g; # undo escaping'

Se o sed (como ssed ) oferecer suporte a expressões regulares semelhantes a perl, você poderá usar operadores de look-around:

ssed -R 's/(?<!\(TAB\))(\(TAB\)){2,8}(?!\(TAB\))/(TAB)/g'

Ou use perl diretamente:

perl -lpe 's/(?<!\(TAB\))(\(TAB\)){2,8}(?!\(TAB\))/(TAB)/g'

AT & T (ast-aberto) sed , com a opção -A / -X suporta um tipo de expressões regulares estendidas que chamam de aumentadas que têm uma negação operador ( x! ) e conjunção operador ( x&y ). Lá, (.{5}&(\(TAB\))!) corresponde a uma sequência de 5 caracteres que não é (TAB) . Então, com esse sed , você pode fazer algo como:

sed -A '
  :1
    s/(^.{0,4}|.{5}&(\(TAB\))!)(\(TAB\)){2,8}(.{0,4}$|.{5}&(\(TAB\))!)/(TAB)/
  t1'
    
por 19.07.2016 / 08:43