Usando sed para remover string ou parágrafo entre delimitador

3

Gostaria de saber para quem remover uma string ou parágrafo entre ((( string )))

Lorem ipsum (((dolor sit amet))), consectetur adipiscing elit. Vestibulum aliquet fringilla est, dictum tempor nunc venenatis at. Sed nec velit sit amet velit cursus imperdiet. Vivamus tincidunt ut nunc quis euismod. Quisque sit amet lorem rhoncus, malesuada justo at, ullamcorper erat.

Portanto, "dolor sit amet" não deve estar no retorno

Aqui está o cmd que tenho por enquanto que detecta o primeiro ((( mas depois pára ...

sed -e "/(((/,/)))/d" file.txt
    
por Warface 10.03.2015 / 15:46

3 respostas

1

Fazer isso para strings de linha única é muito simples:

sed 's/((([^)]*)))//g' file

Se você precisar lidar com strings de múltiplas linhas, fica mais complexo. Uma abordagem seria usar tr para substituir todas as novas linhas com o caractere nulo ( perl ), fazer a substituição e traduzir novamente:

tr '\n' '
perl -0pe 's/\(\(\([^)]+\)\)\)//g;' file
' < file | sed 's/((([^)]*)))//g' | tr '
sed 's/((([^)]*)))//g' file
' '\n'

Como alternativa, você pode usar apenas -0 :

tr '\n' '
perl -0pe 's/\(\(\([^)]+\)\)\)//g;' file
' < file | sed 's/((([^)]*)))//g' | tr '%pre%' '\n'

O perl faz com que -p leia todo o arquivo na memória (isso pode ser um problema para arquivos grandes), o -0 significa "imprimir cada linha", mas devido ao s/// , a "linha "é na verdade o arquivo inteiro. O sed é a mesma ideia de %code% .

    
por 10.03.2015 / 16:19
2
sed -e :p -e '/(((/!b     
'   -e :n -e 's/)))/\     
/;            s/(((.*\n//; tp
$d;N;         s//(((/;     tn'

Isso deve ser feito. Será b ranch away (e consequentemente autoprint) qualquer linha que não corresponda a ((( , mas uma vez encontrada, tenta remover tudo entre a primeira sequência ((( e a primeira% ))) . Se não puder, porque o ))) à direita não é encontrado na linha atual, ele extrai a linha N ext, remove tudo entre ((( e a cabeça da próxima linha e pesquisa novamente. Se chegar ao final da última linha $ enquanto ainda estiver pesquisando por ))) , ela desiste. Dessa forma, ele nunca armazena mais do que uma linha de cada vez, pois remove tudo o que segue ((( cada vez que ele precisa puxar uma nova linha.

Ele deve lidar com quantos pares ((( ))) , como pode ocorrer em uma linha - e não importa se ( ou ) ocorrer entre as duas extremidades - ele buscará 2% ou menos ) e qualquer número de ( .

Depois de encontrar ))) , ele é redefinido para uma pesquisa por ((( e, por isso, não consegue lidar com o próximo par, mesmo depois de cruzar limites de linha nova.

  1. :p - declara o rótulo da ramificação p . O script se divide aqui se puder substituir uma sequência ))) por uma nova linha e, em seguida, remover tudo entre ((( e \n .
  2. /(((/!b - b ranch away - e autoprint pattern space - se não houver seqüências ((( restantes no espaço padrão.
  3. :n - declara a filial : label n . O script ramifica aqui se um ((( for encontrado, mas um ))) não pode ser encontrado na mesma linha.
  4. s/)))/\n/ - substitui a primeira ocorrência de ))) por uma nova linha. Isso só acontece se um ((( já tiver sido correspondido.
  5. s/(((.*\n// - substitua tudo entre o primeiro ((( e o único \n ewline no espaço padrão.
  6. tp - t est para uma substituição bem-sucedida; se verdadeiro, ramifique-se para rotular :p .
  7. $d;N - a última substituição não foi bem sucedida; se a linha atual for a $ last d elete, mais anexe o N ext ao espaço de padrão.
  8. s//(((/;tn - repete a última regexp e substitui todos os que estão entre os ((( e a nova linha que acabou de ser adicionada para ((( , depois ramifique para a etiqueta :n .
por 10.03.2015 / 18:45
1

Tente

sed 's/((([^)]*)))//' file

ou provavelmente ainda melhor em sua frase

sed 's/ ((([^)]*)))//' file
    
por 10.03.2015 / 15:52