当某些术语之间可能没有空格时,如何拆分一行文本中的项目?

Posted

技术标签:

【中文标题】当某些术语之间可能没有空格时,如何拆分一行文本中的项目?【英文标题】:How do I break apart items in a line of text when there may not be space between some terms? 【发布时间】:2019-07-12 16:21:44 【问题描述】:

在 MATLAB 中,我有一段需要拆分的文本。这是此类文本的一个示例:

ROW  SHORT-NAME             TYPE y1             y2             yRef           eq_lhs         eq_rhs         eq_ref         errorCon       tolerance      isConverged
1    CmpFan.S_Qhx.integ_TmatI    +6.3631e+002   +0.0000e+000   +6.3631e+002   TgasPath       Tmat           TgasPath       +1.0000e+000   +1.0000e-004   FALSE     DY1I1
2    CmpL.S_Qhx.integ_Tmat I    +8.0865e+002   +0.0000e+000   +8.0865e+002   TgasPath       Tmat           TgasPath       +1.0000e+000   +1.0000e-004   FALSE     DY2I1
3    CmpH.S_Qhx.integ_Tmat I    +1.2874e+003   +0.0000e+000   +1.2874e+003   TgasPath       Tmat           TgasPath       +1.0000e+000   +1.0000e-004   FALSE     DY3I1
4    BrnPri.S_Qhx.integ_TmatI    +2.8494e+003   +0.0000e+000   +2.8494e+003   TgasPath       Tmat           TgasPath       +1.0000e+000   +1.0000e-004   FALSE     DY4I1
5    TrbH.S_Qhx.integ_Tmat I    +3.3983e+003   +0.0000e+000   +3.3983e+003   TgasPath       Tmat           TgasPath       +1.0000e+000   +1.0000e-004   FALSE     DY5I1
6    TrbL.S_Qhx.integ_Tmat I    +2.6320e+003   +0.0000e+000   +2.6320e+003   TgasPath       Tmat           TgasPath       +1.0000e+000   +1.0000e-004   FALSE     DY6I1
7    BrnAug.S_Qhx.integ_TmatI    +1.6385e+003   +0.0000e+000   +1.6385e+003   TgasPath       Tmat           TgasPath       +1.0000e+000   +1.0000e-004   FALSE     DY7I1
8    dep_FanCustomerBleed  D    +0.0000e+000   +0.0000e+000   +1.0000e-001   CmpFan.CbldAPTMS.WbldFanBleed       0.1            +0.0000e+000   +1.0000e-002   TRUE      DY8I1
9    dep_LPCCustomerBleed  D    +0.0000e+000   +0.0000e+000   +1.0000e-001   CmpL.CbldAPTMS.WbldLPCbleed       0.1            +0.0000e+000   +1.0000e-002   TRUE      DY9I1
10   dep_HPCCustomerBleed  D    +3.0000e+000   +3.0000e+000   +1.0000e-001   CmpH.CbldAPTMS.WbldHPCbleed       0.1            +0.0000e+000   +1.0000e-002   TRUE      DY10I1
11   dep_HPCCustomerBleedMidD    +0.0000e+000   +0.0000e+000   +1.0000e-001   CmpH.CbldAPTMSmid.WbldHPCmidBleed    0.1            +0.0000e+000   +1.0000e-002   TRUE      DY11I1
12   dep_HPXhigh           D    +2.0000e+002   +2.0000e+002   +2.0000e+002   ShH.HPX        HPXhigh        HPXhigh        +0.0000e+000   +1.0000e-004   TRUE      DY12I1
13   dep_HPXlow            D    +5.0000e+002   +5.0000e+002   +5.0000e+002   ShL.HPX        HPXlow         HPXlow         +0.0000e+000   +1.0000e-004   TRUE      DY13I1
14   FlowControl.dep_Tt    D    +8.6941e+002   +9.2300e+002   +9.2300e+002   Fl_I.Tt        Fl_O.Tt        FlowControl.Fl_O.Tt-5.8056e-002   +1.0000e-004   FALSE     DY14I1
15   FlowControl.dep_Pt    D    +7.0096e+001   +8.5000e+001   +8.5000e+001   Fl_I.Pt        Fl_O.Pt        FlowControl.Fl_O.Pt-1.7534e-001   +1.0000e-004   FALSE     DY15I1
16   FlowControl.dep_W     D    +8.0000e-002   +5.4000e-001   +5.4000e-001   Fl_I.W         Fl_O.W         FlowControl.Fl_O.W-8.5185e-001   +1.0000e-004   FALSE     DY16I1
17   MoveCCA.dep_Tt        D    +1.7141e+003   +1.7310e+003   +1.7310e+003   Fl_I.Tt        Fl_O.Tt        MoveCCA.Fl_O.Tt-9.7494e-003   +1.0000e-004   FALSE     DY17I1
18   MoveCCA.dep_Pt        D    +7.0096e+002   +6.9900e+002   +6.9900e+002   Fl_I.Pt        Fl_O.Pt        MoveCCA.Fl_O.Pt+2.8001e-003   +1.0000e-004   FALSE     DY18I1
19   MoveCCA.dep_W         D    +3.4000e+001   +2.2000e+001   +2.2000e+001   Fl_I.W         Fl_O.W         MoveCCA.Fl_O.W +5.4545e-001   +1.0000e-004   FALSE     DY19I1
20   dep_CCAflow           D    +3.4000e+001   +3.4000e+001   +3.4000e+001   CmpH.B_CCA.WbldCCAflow        CCAflow        +0.0000e+000   +1.0000e-004   TRUE      DY20I1
21   ShH.integrate_Nmech   I    -2.6321e+003   +0.0000e+000   +2.4194e+004   trqNet         0.0000         trqIn          -1.0879e-001   +1.0000e-004   FALSE     DY21I1
22   ShL.integrate_Nmech   I    -5.1547e+003   +0.0000e+000   +3.0562e+004   trqNet         0.0000         trqIn          -1.6866e-001   +1.0000e-004   FALSE     DY22I1
23   DESIGN_OPR            D    +5.0176e+001   +5.0000e+001   +5.0000e+001   Overall_PR     D_OPR          50.0           +3.5200e-003   +1.0000e-004   FALSE     DY23I1
24   DESIGN_T41            D    +3.7465e+003   +3.5500e+003   +3.8000e+003   TrbH.Fl_I.Tt   D_T41          3800.0         +5.1708e-002   +1.0000e-004   FALSE     DY24I1
25   DESIGN_CombinedFanPR  D    +5.1200e+000   +4.9000e+000   +5.0000e+001   CmpFan.PR*CmpL.PRD_FANPR        50.0           +4.4000e-003   +1.0000e-004   FALSE     DY25I1
26   DESIGN_ThirdStreamFlowD    +9.9099e-002   +9.2500e-002   +1.3000e-001   ThirdStreamFlowD_ThirdStreamFlow0.13           +5.0762e-002   +1.0000e-004   FALSE     DY26I1
27   DESIGN_RMIX           D    +8.2279e-001   +1.0500e+000   +1.0500e+000   Mixer.RMIX     D_RMIX         1.05           -2.1639e-001   +1.0000e-004   FALSE     DY27I1
28   DESIGN_Wc             D    +4.2158e+002   +4.2500e+002   +4.0000e+002   CmpFan.Fl_I.Wc D_WAC          400.0          -8.5534e-003   +1.0000e-004   FALSE     DY28I1

每一行都有相同类型的信息,但不幸的是它的产生方式,术语之间不一定有空格。发生这种情况时,很难/不可能知道在哪里拆分术语。我可以在中间丢失一些字符串信息列,但我仍然需要能够以某种方式获取数字。

对于像 13 行这样的东西间隔很好,像下面这样的东西很好用(其中一行存储在变量“txt”中):

>>asCells = textscan(txt,'%d %s %c %f %f %f %s %s %s %f %f %s %s');
>> depTxt  = asCells21
depTxt =
    'dep_HPXlow'
>> type    = asCells3
type =
    'D'
>> y1      = asCells4
y1 =
   500
>> y2      = asCells5
y2 =
   500
>> yRef    = asCells6
yRef =
   500
>> lhsTxt  = asCells71
lhsTxt =
    'ShL.HPX'
>> rhsTxt  = asCells81
rhsTxt =
    'HPXlow'
>> depTxt  = asCells91
depTxt =
    'HPXlow'
>> err     = asCells10
err =
     0
>> tol     = asCells11
tol =
                    0.0001
>> if strncmp('TRUE',asCells121,4), conv = 1, else, conv = 0, end
conv =
     1

对于像第 11 行这样的东西,因为第一个字符串和字符一起运行,所以根本不工作,抛出格式字符串。同样,它不可能知道“CmpH.CbldAPTMSmid.WbldHPCmidBleed”片段应该被分解为“CmpH.CbldAPTMSmid.Wbld”和“HPCmidBleed”。如果以后有办法仍然获得编号的项目和收敛标志,我会丢失 eq_lhs、eq_rhs 和 eq_ref 信息,但这就是我苦苦挣扎的地方。

我可以像这样抓取第一个字符串(我确实需要保留):

asCells = textscan(txt,'%d %s',1);
>> depTxt  = asCells21
depTxt =
    'dep_HPCCustomerBleedMidD'

但我不确定如何根据是否进入 TYPE 列有条件地去除最后一个字符。

我注意到所有实际数字都有一个前导加号或减号,并且采用科学计数法(在这种情况下,eq_ref 列中的数字实际上是字符串)。所以我尝试使用正则表达式来获取这样的数值:

>> asCells=regexp(txt,'[+-]\d+\.?\d*([eE][+-]?\d+)?','match','forceCellOutput');
>> y1      = str2double(asCells11)
y1 =
     0
>> y2      = str2double(asCells12)
y2 =
     0
>> yRef    = str2double(asCells13)
yRef =
                       0.1
>> err     = str2double(asCells14)
err =
     0
>> tol     = str2double(asCells15)
tol =
                      0.01

这似乎工作正常,但我不知道如何将它与抓住前面的字符串结合起来(特别是需要有条件地去除 I 或 D TYPE 字符)。当基于间距的行中的哪个术语不一致时,我也不确定如何获得收敛标志。我可以正则表达式搜索每行上的字符串 TRUE 或 FALSE 吗?我想我已经很接近了,但我正在为如何将所有部分组合在一起而苦苦挣扎。

【问题讨论】:

你不能用另一种语言编辑这个文本吗? 【参考方案1】:

这是一个解决方案,除了 eq_lhseq_rhseq_ref 之外,您都可以使用。必须执行 2 遍正则表达式,因为我无法从第一遍的前瞻表达式中捕获 TYPE(也许它可能,但我不太清楚如何......)。

% load data from txt file
fptr = fopen('myData.txt');
s = fread(fptr, inf, 'uint8=>char');
fclose(fptr);
s = s';

% expressions w/named tokens
exprVarType = '(I|D)(?=\s+[+-])';
exprLineStart = '(?<row>\d+)\s+(?<shortName>[^\s]+(?=(\s*I|\s*D|(\s+(I|D)))))+[^+-]+';
exprSciNot1 = '(?<y1>[+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?)';
exprSciNot2 = '(?<y2>[+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?)';
exprSciNot3 = '(?<yref>[+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?)';
exprSciNot4 = '(?<errorCon>[+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?)';
exprSciNot5 = '(?<tolerance>[+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?)';

% concatenate regexs
myExpr = strcat(exprLineStart, exprSciNot1, '\s+', exprSciNot2,...
    '\s+', exprSciNot3, '[^+-]+', exprSciNot4, '\s+', exprSciNot5, '\s+',...
    '(\w+)', '\s+', '([^\r\n]+)');

% first pass: collect all variables except
% 3. Type
% 7. eq_lhs
% 8. eq_rhs
% 9. eq_ref
myData = regexp(s, myExpr, 'names');

% second pass: collect variable type
% couldnt capture this on the first pass because its part of a lookahead
% expression
varType = regexp(s, exprVarType, 'match');
% assign varType to the myData struct
[myData.varType] = deal(varType:);

【讨论】:

在尝试使用您的代码时,我意识到另一个有效的 TYPE 是 C(我认为这是唯一的另一个)。只需快速更改 exprVarType 和 exprLineStart 就可以了。然后我还添加了几行将数字转换为结构中的数字字段而不是字符数组字段。谢谢! 我现在尝试遇到一个新问题。在同一种文件的不同文本块中,代码没有正确处理这一行:31 dep_mixer_total_area D +1.0738e+003 +1.0738e+003 +1.0738e+003 Mixer.Fl_I1.Aphy + Mixer.Fl_I2.AphyMixer.areaMixedDP_MIXEDAREA +0.0000e+000 +1.0000e-004 TRUE DY31I1 这是因为 eq_lhs 表达式中间的加号。关于如何对这种情况进行调整有什么建议吗?我认为它必须类似于在加号(可能还有空格)之后检测非数字字符。 我认为问题在于表达式[^+-]+ 我会考虑其他占位符可以放在中间的 3 列中并尽快回复您!

以上是关于当某些术语之间可能没有空格时,如何拆分一行文本中的项目?的主要内容,如果未能解决你的问题,请参考以下文章

有没有一种简单的方法可以将由空格字符分隔的一行输入拆分为 C++ 中的整数?

Hadoop 计算所有拆分中所需的术语

在 UITextview 中的单词中间点击空格时光标移动最后一行

如何把excel中的空白转换为数字

怎样消除参考文献中的方括号和内容之间的空格?

如何在 TableRow 中的文本视图之间添加空格?