在文本文件中更改具有不同模式的符号

在文本文件中更改具有不同模式的符号

我有一个文本文件。这是一个大文本文件,该文件包含一些如下所示的模式:

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

...就像这样,

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

我想要这样的输出

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

我的意思是我只想将 () 更改为仅包含数字的 []。请帮我

答案1

sed

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

[0-9,]*是匹配任意数量的数字和逗号的正则表达式。我将它包含在其中,\(\)以便我可以在替换字符串中将其重用为\1.不带反斜杠的简单括号代表其自身。它们被替换为[](在替换字符串中没有特殊含义)。

答案2

Python 3 脚本解决方案

下面的脚本是一个更明确的“手动”解决方案,它不使用正则表达式,但在完成这项工作时需要考虑一些额外的注意事项。其操作的关键是脚本打开以读取我们在命令行上提供的任何文件,迭代每行中的每个字符,寻找括号。如果我们看到括号,我们就记录里面的内容,然后扔掉逗号后,我们决定这是否是数字字符串。如果它是数字字符串 - 记录的项目将进入单词列表,稍后使用带有分隔符的.join()函数将其重建为一行", "。非常坦率的。

 #!/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))

测试运行:

我随意使用 OP 的输入来包含额外的 2 行,其中包含几个不同的测试用例。

$ # 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)

对于 40,000 行文本,它执行得相当快:

$ 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

可能的改进建议(以及解决斯蒂芬提到的事情之一) 是将if item.replace(",","").isdigit()线改为if item.replace(",","").replace(".","").isdigit().这也将使我们能够处理浮点数(例如 3.1415)。

冗长?是的。明确?是的。有效吗?嗯,是。

答案3

sed -E 's/[(](([0-9]+,?)+)[)]/[\1]/g'

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

我们正在寻找正则表达式 [0-9]+,?至少出现一次并且同时出现,由 ( 和 ) 括号包围。成功时外括号更改为 [ ]。

第二个 sed 语句是上述语句的 POSIXly 版本。

相关内容