Python正则表达式对文件名的某些部分重新排序:从名称中删除重复项并拆分组

2024-09-30 14:23:38 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试使用Python(3.8)中的正则表达式重命名多个文件,重新排列文件名以保持一致性。目的是在适当的情况下,将零件号说明移到文件的开头。并非所有文件都包含PNo

我在测试中使用的一些示例文件名结构如下所示。我试图捕捉一些可能的变化,这些变化可能与之前输入的内容有关

Test Document One PNo 6477 Rev 2
Test Document TwoPno5555 - Rev 1
Test Document 3 PNo5343 rev 2
PNo 6478 - Test Document 4 Rev1
Test Document Five Pno 3333

在大多数情况下,我的正则表达式工作正常,但有两件事我仍然希望实现:

文档2和文档4有一个现有的连字符,当组合组以创建新文件名时,这些连字符会重复。我曾尝试将[-]添加到正则表达式中,但它破坏了第三个组,并且我无法在名称中没有连字符的文件中使用它。解决这个问题的最佳方法是什么

第二,当现有零件号的字母数字字符串之间没有空格时,我希望将其添加到新文件名中。这可以通过使用现有的python组来实现吗?我确实考虑把PNO分割成两个单独的组,但是认为其他文件名(例如日期)中的4位数字会把这个问题搞糟。p>

我很乐意对我在这里所做的事情提出一些批评。这是我第一次尝试编写正则表达式,所以如果有更好的方法,我洗耳恭听。Thx

PNoRegex = re.compile(r"""^(.*?)       
                   (PNo\s\d{4}|PNo\d{4}|Pno\s\d{4}|Pno\d{4})    # part number details
                   \s*             #remove white space after PNo string
                   (.*)$          # all text after Part No
                   """, re.VERBOSE)

for originalFile in os.listdir('.'):
    fileNameText = PNoRegex.search(originalFile)

# Skip files without a Regex match
if fileNameText == None:
    continue
# separate the groups
beforePNo   = fileNameText.group(1)
PNo         = fileNameText.group(2)
afterPNo    = fileNameText.group(3)

# Form the reordered filename.
newFileName = PNo + ' - ' + beforePNo + afterPNo

编辑:添加文件的屏幕截图

List of files before regex operation

After performing operation


Tags: 文件方法文档test文件名group情况rev
2条回答

使用re.sub

re.sub(r'(?i)^(.*?)\s*(PNo)\s*(\d{4})\s*(?:-\s*)?(.*)$', r'\2 \3 - \1 \4', string)

proof

说明:

NODE                     EXPLANATION
                                        
  (?i)                     set flags for this block (case-
                           insensitive) (with ^ and $ matching
                           normally) (with . not matching \n)
                           (matching whitespace and # normally)
                                        
  ^                        the beginning of the string
                                        
  (                        group and capture to \1:
                                        
    .*?                      any character except \n (0 or more times
                             (matching the least amount possible))
                                        
  )                        end of \1
                                        
  \s*                      whitespace (\n, \r, \t, \f, and " ") (0 or
                           more times (matching the most amount
                           possible))
                                        
  (                        group and capture to \2:
                                        
    PNo                      'PNo'
                                        
  )                        end of \2
                                        
  \s*                      whitespace (\n, \r, \t, \f, and " ") (0 or
                           more times (matching the most amount
                           possible))
                                        
  (                        group and capture to \3:
                                        
    \d{4}                    digits (0-9) (4 times)
                                        
  )                        end of \3
                                        
  \s*                      whitespace (\n, \r, \t, \f, and " ") (0 or
                           more times (matching the most amount
                           possible))
                                        
  (?:                      group, but do not capture (optional
                           (matching the most amount possible)):
                                        
    -                        '-'
                                        
    \s*                      whitespace (\n, \r, \t, \f, and " ") (0
                             or more times (matching the most amount
                             possible))
                                        
  )?                       end of grouping
                                        
  (                        group and capture to \4:
                                        
    .*                       any character except \n (0 or more times
                             (matching the most amount possible))
                                        
  )                        end of \4
                                        
  $                        before an optional \n, and the end of the
                           string

您可以使用字符类并匹配可选的空白字符,将替换缩短为(P[nN]o)\s?(\d{4})

如果pno和数字之间有空格,可以使用2个捕获组,而不是1个

要匹配可选连字符,可以使用字符类[-\s]*扩展匹配空格字符或连字符

这将为当前示例数据中的零件生成单独的组

^(.*?)(P[nN]o)\s?(\d{4})[-\s]*(.*)$

Regex demo

相关问题 更多 >