Alterando o símbolo com um padrão diferente em um arquivo de texto

2

Eu tenho um arquivo de texto. É um grande arquivo de texto e este arquivo contém alguns padrões como o seguinte:

(1), (3), (1,2,3), (1,2,3,4,5,6,7,8,9)

... e assim,

(Fig1) (Fig1,Fig2), (Table-1, Table-2) etc.

Eu quero a saída como esta

[1], [3], [1,2,3], [1,2,3,4,5,6,7,8,9], (Fig1) (Fig1,Fig2), (Table-1, Table-2)

Quer dizer, só quero alterar o () para [], que contém apenas números. Por favor me ajude

    
por Masum Billah 12.05.2017 / 07:36

3 respostas

2

com sed :

sed 's/(\([0-9,]*\))/[]/g' filename.txt

[0-9,]* é uma expressão regular que corresponde a qualquer número de dígitos e vírgulas. Eu coloquei em \(\) para que eu pudesse reutilizá-lo na string de substituição como . O parêntese simples sem barras invertidas é o mesmo. Eles são substituídos pelo [] (que não tem um significado especial na string de substituição).

    
por 12.05.2017 / 07:43
1

Solução de script do Python 3

O script abaixo é uma solução explícita mais "manual" que não usa expressões regulares, mas faz o trabalho com algumas considerações extras. A chave para o seu funcionamento é que o script é aberto para a leitura de qualquer arquivo que tenhamos fornecido na linha de comando, itera sobre cada caractere em cada linha, procurando encontrar colchetes. Se virmos colchetes, gravamos o que estiver dentro e, depois de jogarmos fora as vírgulas, decidimos se é uma sequência numérica ou não. Se for uma string numérica - os itens gravados vão para a lista de palavras, que depois é reconstruída em uma linha usando a função .join() com ", " como separador. Razoavelmente direto.

 #!/usr/bin/env python3
import sys

with open(sys.argv[1]) as fd:
    for line in fd:
        # we're going to store everything into list of words
        # and record individual characters into 'item' string
        # and rebuild everything as we go.
        words = []
        item_found = False
        item = ""
        counter = 0
        for char in line:
            # if we see ( or [ we start recording chars
            # difference is that [ means item already been edited
            # so no need to do anything - just put it into words list
            # as is
            if char == "(" or char == "[":
                item_found = True
                counter = counter + 1
                continue

            if char == ")":
                item_found = False
                if item.replace(",","").isdigit():
                   words.append("[" + item + "]")
                else:
                   words.append("("+item+")")
                item = ""

            if char == "]":
              item_found = False
              item = item + char
              words.append("[" + item) 
              item = ""

            if item_found:
                item = item + char

        # if we didn't see any open brackets or no closing brackets
        # just print the line as is - otherwise give us the altered one
        if counter == 0 or item_found:
            print(line.strip())
        else:
            print(", ".join(words))

Execução de teste:

Eu tomei liberdade com a entrada do OP para incluir duas linhas extras que incluem pares de casos de teste diferentes.

$ # original input file
$ cat input.txt
(1), (3), (1,2,3), (1,2,3,4,5,6,7,8,9), (Fig1) (Fig1,Fig2), (Table-1, Table-2)
(table-25),[1,2,3],(figure-35)
(figure-1),(figure-2)
$ # script output 
$ ./change_brackets.py input.txt                                                          
[1], [3], [1,2,3], [1,2,3,4,5,6,7,8,9], (Fig1), (Fig1,Fig2), (Table-1, Table-2)
(table-25), [1,2,3], (figure-35)
(figure-1), (figure-2)

Com 40.000 linhas de texto, ele é bastante rápido:

$ wc -l big_input.txt                                                                     
40000 big_input.txt
$ time ./change_brackets.py big_input.txt  > /dev/null                                    
    0m01.64s real     0m01.60s user     0m00.01s system

Possível sugestão de melhoria (e para aborda uma das coisas que Stephane mencionou ) é alterar if item.replace(",","").isdigit() line para if item.replace(",","").replace(".","").isdigit() . Isso nos permitirá lidar com números de ponto flutuante (como 3.1415) também.

Comprimento? Sim. Explicito Sim. Trabalho ? Bem, sim.

    
por 12.05.2017 / 08:28
1
sed -E 's/[(](([0-9]+,?)+)[)]/[]/g'

sed -e 's/(\(\([0-9]\{1,\},\{0,\}\)\{1,\}\))/[]/g'

Estamos procurando o regex [0-9] +? ocorrendo pelo menos uma vez e ao mesmo tempo limitada por (e) colchetes. Os colchetes externos são alterados para [] no sucesso.

A segunda declaração sed é a versão POSIXly do acima.

    
por 12.05.2017 / 20:50