In [1]:
import re
opt_pattern_format = "({})?"

In [2]:
row_pattern_mfm_multpergroup = r"""^(?P<multpergroup>[ GMP])"""                           
row_pattern_mfm_level_names = r"""(?P<level>\d)(?P<shortname>\S{2})(?P<longname>\S+)\s+"""
row_pattern_mfm_typelength = r"""(?P<type>[ABCDFILNPT])?(?P<length>\d{3})(?P<scale>\d)""" 
row_pattern_mfm_null = r"""(?P<null>[NF])"""                                              
row_pattern_mfm_descsub = r"""(?P<descsub>[DS])"""

In [3]:
row_pattern_mfm_ddm = re.compile(row_pattern_mfm_multpergroup +                         
                                 row_pattern_mfm_level_names +                          
                                 opt_pattern_format.format(row_pattern_mfm_typelength) +
                                 opt_pattern_format.format(row_pattern_mfm_null) +      
                                 opt_pattern_format.format(row_pattern_mfm_descsub))

In [4]:
line = """ 1ABCAMPO-ALFA                      A0780ND"""
#line = """M1AICAMPO-MULTIPLO                  N0030N"""
#line = """P1AJGP-SEM-MULTIPLO                  0000"""

In [5]:
match = row_pattern_mfm_ddm.match(line)
match.groupdict()


Out[5]:
{'descsub': 'D',
 'length': '078',
 'level': '1',
 'longname': 'CAMPO-ALFA',
 'multpergroup': ' ',
 'null': 'N',
 'scale': '0',
 'shortname': 'AB',
 'type': 'A'}