Регулярные выражения/анализ вывода dig/извлечение текста из двойных кавычек
Вопрос
Мне нужна помощь в понимании некоторых регулярных выражений.Я запускаю команду dig и мне нужно использовать ее выходные данные.Мне нужно проанализировать его и аккуратно упорядочить в виде массива, используя php.
dig выводит что-то вроде этого:
m0.ttw.mydomain.tel. 60 IN TXT ".tkw" "1" "20090624-183342" "Some text here1"
m0.ttw.mydomain.tel. 60 IN TXT ".tkw" "1" "20090624-183341" "Some text here2"
Я хочу получить это:
Array
(
[0] => Array
(
[0] => .tkw
[1] => 1
[2] => 20090624-183342
[3] => Some text here1
)
[1] => Array
...
)
Мне просто нужно содержимое внутри двойных кавычек.я может проанализировать вывод раскопок построчно, но я думаю, что было бы быстрее, если бы я просто запустил сопоставление шаблонов регулярных выражений для всего этого...
Мысли?
Решение
Это приближается к одной строке
preg_match_all( '/"([^"]+)"\s*"([^"]+)"\s*"([^"]+)"\s*"([^"]+)"/', $text, $matches, PREG_SET_ORDER );
print_r( $matches );
однако из-за особенностей работы функций preg_match* полное совпадение включается в индекс 0 каждой группы совпадений.Вы могли бы это исправить, если бы действительно этого хотели.
array_walk( $matches, create_function( '&$array', 'array_shift( $array );return $array;' ) );
Другие советы
Я не уверен насчет регулярных выражений PHP, но в Perl RE будет простым:
my $c = 0;
print <<EOF;
Array
(
EOF
foreach (<STDIN>) {
if (/[^"]*"([^"]*)"\s+"([^"]*)"\s+"([^"]*)"\s+"([^"]*)"/) {
print <<EOF;
[$c] => Array
(
[0] = $1
[1] = $2
[2] = $3
[3] = $4
)
EOF
$c++;
}
}
print <<EOF;
)
EOF
Это имеет некоторые ограничения, а именно:
- Это не работает, если текст в кавычках может содержать кавычки (например,
\"
) - Он жестко запрограммирован для поддержки только четырех значений в кавычках.
Код:
<?php
$str = 'm0.ttw.mydomain.tel. 60 IN TXT ".tkw" "1" "20090624-183342" "Some text here1"
m0.ttw.mydomain.tel. 60 IN TXT ".tkw" "1" "20090624-183341" "Some text here2"';
header('Content-Type: text/plain');
$matches = array();
preg_match_all('/(".*").*(".*").*(".*").*(".*")/U', $str, $matches, PREG_SET_ORDER);
print_r($matches);
?>
Выход:
Array ( [0] => Array ( [0] => ".tkw" "1" "20090624-183342" "Some text here1" [1] => ".tkw" [2] => "1" [3] => "20090624-183342" [4] => "Some text here1" ) [1] => Array ( [0] => ".tkw" "1" "20090624-183341" "Some text here2" [1] => ".tkw" [2] => "1" [3] => "20090624-183341" [4] => "Some text here2" ) )
Совершенно не то, что вы просили, но оно работает, может использоваться для строк с любым количеством кавычек и имеет то преимущество, что оно более читабельно, чем ваше среднее регулярное выражение (за счет гораздо большего количества кода).
class GetQuotedText {
const STATE_OUTSIDE = 'STATE_OUTSIDE';
const STATE_INSIDE = 'STATE_INSIDE';
static private $input;
static private $counter;
static private $state;
static private $results;
static private $current;
static private $full;
static private $all;
static private function setInput($string) {
$this->input = $string;
}
static private function init($string) {
self::$current = array();
self::$full = array();
self::$input = $string;
self::$state = self::STATE_OUTSIDE;
}
static public function getStrings($string) {
self::init($string);
for(self::$counter=0;self::$counter<strlen(self::$input);self::$counter++){
self::parse(self::$input[self::$counter]);
}
self::saveLine();
return self::$all;
}
static private function parse($char) {
switch($char){
case '"':
self::encounteredToken($char);
break;
case "\n": //deliberate fall through for "\n" and "\r"
case "\r":
self::encounteredToken($char);
break;
default:
if(self::$state == self::STATE_INSIDE) {
self::action($char);
}
}
}
static private function encounteredToken($token) {
switch($token) {
case '"':
self::swapState();
break;
case "\n": //deliberate fall through for "\n" and "\r"
case "\r":
self::saveArray();
self::saveLine();
break;
}
return;
}
static private function swapState() {
if(self::$state == self::STATE_OUTSIDE) {
self::$state = self::STATE_INSIDE;
}
else {
self::$state = self::STATE_OUTSIDE;
self::saveArray();
}
}
static public function saveLine() {
self::$all[] = self::$full;
self::$full = array();
//reset state when line ends
self::$state = self::STATE_OUTSIDE;
}
static private function saveArray() {
if(count(self::$current) > 0) {
self::$full[] = implode ('',self::$current);
self::$current = array();
}
}
static private function action($char) {
self::$current[] = $char;
}
}
$input = 'm0.ttw.mydomain.tel. 60 IN TXT ".tkw" "1" "20090624-183342" "Some text here1"' . "\n" .
'm0.ttw.mydomain.tel. 60 IN TXT ".tkw" "1" "20090624-183341" "Some text here2"';
$strings = GetQuotedText::getStrings($input);
print_r($strings);