Camping_RIDER: Spezielle Textdatei mit PHP auslesen und speichern

Beitrag lesen

Aloha ;)

...und hier der PHP-Code mit rekursiv aufgerufenen Closures:

// das Posting war zu lang
<?php

function decode_strange($raw) {
	$decoded = [];
	
	$lines = explode("\n", $raw);
	
	// remove "\r" character if present
	foreach ($lines as $i=>$line) {
		
		$lines[$i] = (strrpos($line, "\r") === strlen($line)-1)
			? substr($lines[$i], 0, -1)
			: $lines[$i];
			
		// better-to-parse formatting: 
		// "[category]" -> "category"
		// "data"/" data" -> ".data"
		// ".prop" -> "..prop" and so on
		if (preg_match('~^\[([^\]]+)\]$~', trim($lines[$i]), $matches)) {
			$lines[$i] = $matches[1];
		} else {
			// remove starting whitespaces
			if (preg_match('~^\s*(.+)$~', $lines[$i], $matches)) {
				// add another dot in front to make space for category
				$lines[$i] = '.'.$matches[1];
			}
		}
	}
	
	$parse_layer = function ($layer_lines, $depth, $func) {
		$layer = [];
		$sub_heading = '';
		$sub_lines = [];
		foreach ($layer_lines as $line) {
			// count starting dots
			if (preg_match('~^(\.*)([^\.].*)$~', $line, $matches)) {
				$dotcount = strlen($matches[1]);
				// if count of starting dots matches depth, this is a new heading or property
				if ($dotcount == $depth) {
					if (preg_match('~(.+)=(.*)~', $matches[2], $prop_matches)) {
						// this is a property
						// arrayfy for case of duplicate headings
						if (!array_key_exists($prop_matches[1], $layer)) {
							$layer[$prop_matches[1]] = [];
						}
						$layer[$prop_matches[1]][] = $prop_matches[2];
					} else {
						// if we already had a heading, save old heading in layer
						if ($sub_heading !== '') {
							// arrayfy for case of duplicate headings
							if (!array_key_exists($sub_heading, $layer)) {
								$layer[$sub_heading] = [];
							}
							$layer[$sub_heading][] = $func($sub_lines, $depth + 1, $func);
						}
						$sub_heading = $matches[2];
						$sub_lines = [];
					}
				} elseif ($dotcount > $depth) {
					$sub_lines[] = $line;
				} else {
					throw new Exception('Dot count does not match: Found '.$dotcount.' dots in depth '.$depth);
				}
			}
		}
		
		// if there is a leftover heading, save it
		if ($sub_heading !== '') {
			// arrayfy for case of duplicate headings
			if (!array_key_exists($sub_heading, $layer)) {
				$layer[$sub_heading] = [];
			}
			$layer[$sub_heading][] = $func($sub_lines, $depth + 1, $func);
		} else {
			// this means there was not even one heading!
		}
		
		// de-arrayfy where possible
		foreach ($layer as $li => $larr) {
			if (count($larr) == 1) {
				$layer[$li] = $layer[$li][0];
			}
		}
		
		return $layer;
	};
	
	return $parse_layer($lines, 0, $parse_layer);
}

function encode_strange ($data, $newline = "\r\n") {
	$parse_layer = function($layer_data, $depth, $newline, $func) {
		$depth_prefix = ($depth >= 1)
			? ' ' : '';
		for ($i = 1; $i < $depth; $i++) {
			$depth_prefix .= '.';
		}
		$depth_suffix = '';

		if ($depth == 0) {
			$depth_prefix = '[';
			$depth_suffix = ']';
		}
		
		$ltext = '';
		foreach ($layer_data as $ltitle => $lelm) {
			// only properties are non-arrays
			if (!is_array($lelm)) {
				$ltext .= $depth_prefix.$ltitle.$depth_suffix.'='.$lelm.$newline;
			} else {
				// numeric indices mean this is a list
				$fully_numeric = true;
				foreach (array_keys($lelm) as $lek) {
					$fully_numeric = $fully_numeric && is_numeric($lek);
				}
				if ($fully_numeric) {
					// add each list element
					foreach ($lelm as $llistelm) {
						$ltext .= $depth_prefix.$ltitle.$depth_suffix.$newline;
						$ltext .= $func($llistelm, $depth+1, $newline, $func);
					}
				} else {
					// add this single element
					$ltext .= $depth_prefix.$ltitle.$depth_suffix.$newline;
					$ltext .= $func($lelm, $depth+1, $newline, $func);
				}
			}
		}
		return $ltext;
	};
	
	return $parse_layer($data, 0, $newline, $parse_layer);
}

$decoded = decode_strange(file_get_contents('./strangefile.txt'));

echo '<pre>';
echo print_r($decoded, true);
echo '</pre>';

file_put_contents('./strangefile_reencoded.txt', encode_strange($decoded));

?>