正規表現/発掘出力の解析/二重引用符からのテキストの抽出
質問
いくつかの正規表現を理解するのに助けが必要です。 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
...
)
二重引用符内のコンテンツが必要です。 dig出力を1行ずつ解析することができますが、すべてに対して正規表現パターンマッチングを実行する方が高速だと思います...
思考?
解決
これは1行で終了します
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
これには、いくつかの制限があります:
- 引用符内のテキストに引用符がエスケープされている場合は機能しません(例:
\&quot;
) - 引用符で囲まれた4つの値のみをサポートするようにハードコードされています。
コード:
<?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" ) )
完全にあなたが要求したものではありませんが、それは機能し、任意の数の引用符で文字列に使用でき、平均的な正規表現よりも読みやすいという利点があります(コードがかなり増えます) p>
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);
所属していません StackOverflow