excluindo caracteres da expressão usando sed

2

Eu tenho uma string no formulário

  1. |a Some text, letters or numbers. | Some other text letters or numbers |b some other part of text |c some other letters or numbers

observe que a barra pode estar ativa, como em "números. | Alguns outros" ou com um caractere "| a", "| b", "| c" e assim por diante, potencialmente através de "| z "

mas isso também pode ser

  1. |a Title without any other bars

Em outras palavras, o número de barras é desconhecido.

Eu preciso encontrar duas expressões regulares para usar com o sed:

  1. O primeiro, encontra todo o texto entre | a e | b, ou | b e | c, e assim por diante

em 1), por exemplo,

encontre todo o texto depois de um | mas antes b |, produzindo:

Some text, letters or numbers. | Some other text letters or numbers

encontre todo o texto depois de b | mas antes de c |, cedendo, no exemplo acima:

Some other part of text

  1. Uma segunda expressão é necessária para localizar todo o texto após | a, mas, em vez de parar em | b, simplesmente exclui todas as barras, por conta própria (|) ou com outro caractere | a, | b, | c, etc.

em 1) por exemplo:

Some text, letters or numbers Some other text letters or numbers some other part of text some other letters or numbers

    
por Michael Riordan 07.12.2017 / 16:48

2 respostas

2

Supondo utilitários GNU e um arquivo de dados data ,

  1. grep -Po '(?<=\|a).*(?=\|b)' data

     Some text, letters or numbers. | Some other text letters or numbers 
    
  2. sed -r -e 's/^.?*\|a//' -e 's/\|[a-z]?//g' data

     Some text, letters or numbers.  Some other text letters or numbers  some other part of text  some other letters or numbers 
     Title without any other bars 
    

Altere o |a e o |b para |c e |d , etc., conforme necessário.

Observe que nenhum desses remove o espaço em branco ao redor dos marcadores |x , portanto, o texto tem um espaço à esquerda e um espaço à direita (nenhum dos quais pode ser mostrado aqui). Se você quiser que seja removido também, é necessário incluí-lo como parte do padrão:

grep -Po '(?<=\|a ).*(?= \|b)' data
sed -r -e 's/^.?*\|a ?//' -e 's/ ?\|([a-z] ?)?//g' data

Como escrito aqui, o comando sed unirá as subseções. Se você quiser que eles tenham um espaço entre eles, apenas altere o // no final para / / .

    
por 07.12.2017 / 17:07
1

Não ficou claro para mim se você queria ou não que as letras em seus delimitadores fossem sequenciais ou não, então fui em frente e assumi que você queria lidar com o caso mais difícil de exigir que os delímetros fossem sequenciais (ou seja, |a está emparelhado com |b , mas não com |c ). Não tenho certeza se você pode fazer isso apenas com expressões regulares (pelo menos não sem uma expressão regular extremamente detalhada). De qualquer forma, aqui está um script Python simples que lida com esse caso:

#!/usr/bin/env python2
# -*- coding: ascii -*-
"""parse.py"""

import sys
import re

def extract(string):
    """Removes text between delimters of the form '|START' and '|STOP'
    where START is a single ASCII letter and STOP is the next sequential
    ASCII character (e.g. '|a' and '|b' if START=a and STOP=b or
    '|x' and '|y' if START=x and STOP=y)."""

    # Find the opening delimiter (e.g. '|a' or '|b')
    start_match = re.search(r'\|[a-z]', string)
    start_index = start_match.start()
    start_letter = string[start_index+1]

    # Find the matching closing delimiter
    stop_letter = chr(ord(start_letter) + 1) 
    stop_index = string.find('|' + stop_letter)

    # Extract and return the substring
    substring = string[start_index+2:stop_index]
    return(substring)

def remove(string):

    # Find the opening delimiter (e.g. '|a' or '|b')
    start_match = re.search(r'\|[a-z]', string)
    start_index = start_match.start()
    start_letter = string[start_index+1]

    # Remove everything up to and including the opening delimiter
    string = string[start_index+2:]

    # Remove the desired substrings which occur after the delimiter
    string = re.sub(r'\|[a-z]?', '', string)

    # Return the updated string
    return(string)

if __name__=="__main__":
    input_string = sys.stdin.readline()
    sys.stdout.write(extract(input_string) + '\n')
    sys.stdout.write(remove(input_string))
    
por 07.12.2017 / 18:00