我问了几个关于这方面的问题,我尝试了很多不同的事情,但我并不完全满意。我有以下格式的大量数据
3*O#AA6160 F7 A7 P7 J7 R7 D7 I7 Y7 LHRMIA 1040 1455 * 744 0E
B7 H0 W0 K0 M0 L0 V0 G0 S0 Q0 N0 O0
默认情况下,您在第二行看到的空格是存在的。基本上,从该字符串我试图得到以下
$flightNumber = AA6160;
$from = LHR;
$to = MIA;
$other = 1040 1455 * 744 0E;
$seats = array(
"F" => 7,
"A" => 7,
"P" => 7,
"J" => 7,
"R" => 7,
"D" => 7,
"I" => 7,
"Y" => 7,
"B" => 7,
"H" => 0,
"W" => 0,
"K" => 0,
"M" => 0,
"L" => 0,
"V" => 0,
"G" => 0,
"S" => 0,
"Q" => 0,
"O" => 0,
)
规则如下 行的开头以数字开头(在上面的例子中为3)。第二行是第一行的座位延续。如果我要发布我的完整数据,第三行以4开头,这意味着它与上面的两行无关。
航班号始终以#开头,后跟两个字母和1-4个号码。有时字母和数字之间有空格。这些是我发现的所有类型的航班号
#AA6160
#AA 57
#BA 207
第二行只包含一个座位的延续,没有别的。这是我到目前为止所提出的
while ( $elNum < $elements->length ) {
$flightInfo = $elements->item($elNum)->nodeValue;
if (preg_match('/^\\d/', $flightInfo) === 1) {
if(preg_match('/(\d)+[^#]*?\#(\p{Lu}{2})\s*(\d{1,4})\b\s*([\w. ]+?)(?=\s+\p{Lu}{6})\s([A-Z]{3})([A-Z]{3})(.+)/', $flightInfo, $matches)===1){
$row = $matches[1];
$fltcode = $matches[2].$matches[3];
$ffrom = $matches[5];
$fto = $matches[6];
$other = $matches[7];
$this->flights[$fltcode] = array(
"command" => $terminal_command,
"row" => $row,
"flightNumber" => $fltcode,
"from" => $ffrom,
"to" => $fto,
"other" => $other
);
}
}
++$elNum;
}
我正在努力的主要是座位。我不知道如何从第一行得到我需要的那些,并将它们与输出格式中第二行的那些组合,我需要它们。
我甚至不确定正则表达式是否是这里最好的选择,或者我是否应该在空格上爆炸所有内容并按照这样排序?
对此情况的任何建议表示赞赏。这是一些额外的数据
5*S#DL4386 J9 C9 D9 I9 Z9 W9 Y9 B9 LHRMIA 1235 1705 * 744 0E
M9 S9 H9 Q9 K9 L9 U9 T9 X9 V9
6 #VS 5 J9 C9 D9 I9 Z9 W9 S9 H9 LHRMIA 1235 1705 744 0E
K9 Y9 B9 R9 L9 U9 M9 E9 Q9 X9 N9 O9
7 #IB4637 F9 A9 J9 C9 D9 R9 I. W9 LHRMIA 1415 1825 * 744 0E
Z. Y9 B9 H9 K. M. L. V. S. N. Q. O.
由于
答案 0 :(得分:1)
您可以尝试更简单的方法,但我不能100%确定,这涵盖了您需要的一切。
function yourFunction($input) {
// get the individual words, meaning split on whitespace
$words = preg_split('/\s+/', $input);
// filter the words the best we can
$valuableInput = array_filter($words, function($word) {
$chars = str_split($word);
return count($chars) == 2 && is_int($chars[1]);
});
// Create the mapping between the characters and the numbers
$output = array();
foreach ($valuableInput as $word) {
$chars = str_split($word);
$output[$chars[0]] = $chars[1];
}
return $output;
}
答案 1 :(得分:1)
使用XMLReader而不是DOMDocument进行xml解析的示例,因为它更快并且使用更少的内存。模式设计为更具可读性(使用自由间距模式和命名捕获)和高效(使用锚点,没有无用的unicode字符类,如\p{Lu}
,前瞻或未使用的捕获组)。
$xml = <<<EOD
<?xml version="1.0" encoding="utf-8" ?>
<root xmlns:terminal="http://test.com/terminal">
<terminal:Text>1 #AY5767 F9 A9 P. J9 C9 D9 I9 Y9 LHRMIA 0945 1410 * 777 0E</terminal:Text>
<terminal:Text> B9 H9 K9 M9 L9 V9 S9 N9 Q9 O9 G9 </terminal:Text>
<otherthings>blah blah blah</otherthings>
<terminal:Text>2 #AY5768 F9 A9 P. J9 C9 D9 I9 Y9 ROMMIL 0945 1410 * 777 0E</terminal:Text>
<terminal:Text> B9 H9 K9 M9 L9 V9 S9 N9 Q9 O9 G9 </terminal:Text>
<terminal:Text> E8 G8 R8 S8 T4 U2 </terminal:Text>
</root>
EOD;
$patternFirstLine = <<<EOD
~
\A
[0-9]+ \s+
\# (?<code1> [A-Z]{2} ) \s* (?<code2> [0-9]{1,4} ) \s+
(?<seat1> [A-Z][0-9.] (?: \s+ [A-Z][0-9.] )*+ ) \s+
(?<from> [A-Z]{3} ) (?<to> [A-Z]{3} ) \s+
(?<other> .*\S ) \s*
\z
~x
EOD;
$patternNextLines = <<<EOD
~
\A \s*
(?<seatN> [A-Z][0-9.] (?: \s+ [A-Z][0-9.] )*+ )
\s* \z
~x
EOD;
$parser = new XMLReader();
$parser->xml($xml);
$temp = false;
$results = [];
while($parser->read()) {
while ($parser->name === 'terminal:Text') {
if (preg_match($patternFirstLine, $parser->readInnerXML(), $m)) {
if ($temp) $results[] = $temp;
$temp = [
"flightNumber" => $m['code1'] . $m['code2'],
"from" => $m['from'],
"to" => $m['to'],
"seats" => $m['seat1'],
"other" => $m['other']
];
} elseif ($temp && preg_match($patternNextLines, $parser->readInnerXML(), $m))
$temp['seats'] .= ' ' . $m['seatN'];
else
$temp = false;
$parser->next('Text');
}
}
if ($temp) $results[] = $temp;
$results = array_map(function ($i) {
$seats = explode(' ',$i['seats']);
$i['seats'] = [];
foreach ($seats as $seat)
$i['seats'][$seat[0]] = $seat[1];
return $i;
}, $results);
print_r($results);
注意:在此示例中,我使用XMLReader::xml()
加载xml内容,但XMLReader
的主要兴趣之一是将XMLReader::open
方法与xml uri一起使用。< / p>