2009-11-23 3 views
1

Est-ce possible avec regex?Puis-je utiliser regex pour cela?

J'ai un fichier, et si un '@' est trouvé dans le fichier, le texte après le '@' avec le '@' doit être remplacé par le fichier du même nom qu'après le '@' . Fichier1: "ce texte se trouve dans le fichier 1"
Fichier2: "ce fichier contiendra le texte du fichier1: @ fichier1". File2 after regex: "ce fichier contiendra le texte du fichier 1: ce texte se trouve dans le fichier 1".

Je tiens à le faire avec php et je l'ai entendu dire que la fonction preg est mieux que le ereg, mais tout ce qui fonctionne est très bien avec moi =)

Merci beaucoup!

EDIT:

Il doit être programmé, de sorte qu'il regarde à travers fichier2 sans savoir quels sont les fichiers à concaténer avant qu'il est passé par toutes les occurrences d'un @ :)

Répondre

2

d'abord la grammaire de votre templating est pas un très bon becuase l'analyseur ne peut pas exactement quand le fichier le nom se termine. Ma suggestion serait que vous changiez pour celui qui peut mieux détecter la limite comme {@: filename}.

De toute façon, le code que je donne ci-dessous suit votre question.

<?php 

// RegEx Utility functions ------------------------------------------------------------------------- 

function ReplaceAll($RegEx, $Processor, $Text) { 
    // Make sure the processor can be called 
    if(!is_callable($Processor)) 
     throw new Exception("\"$Processor\" is not a callable."); 

    // Do the Match 
    preg_match_all($RegEx, $Text, $Matches, PREG_OFFSET_CAPTURE + PREG_SET_ORDER); 

    // Do the replacment 
    $NewText = ""; 
    $MatchCount = count($Matches); 
    $PrevOffset = 0; 
    for($i = 0; $i < $MatchCount; $i++) { 
     // Get each match and the full match information 
     $EachMatch = $Matches[$i]; 
     $FullMatch = is_array($EachMatch) ? $EachMatch[0] : $EachMatch; 
     // Full match is      each match if no grouping is used in the regex 
     // Full match is the first element of each match if grouping is used in the regex. 

     $MatchOffset  = $FullMatch[1]; 
     $MatchText  = $FullMatch[0]; 
     $MatchTextLength = strlen($MatchText); 
     $NextOffset  = $MatchOffset + $MatchTextLength; 

     // Append the non-match and the replace of the match 
     $NewText .= substr($Text, $PrevOffset, $MatchOffset - $PrevOffset); 
     $NewText .= $Processor($EachMatch); 

     // The next prev-offset 
     $PrevOffset = $NextOffset; 
    } 
    // Append the rest of the text 
    $NewText .= substr($Text, $PrevOffset); 

    return $NewText; 
} 

function GetGroupMatchText($Match, $Index) { 
    if(!is_array($Match)) 
     return $Match[0]; 

    $Match = $Match[$Index]; 
    return $Match[0]; 
} 

// Replacing by file content ----------------------------------------------------------------------- 

$RegEx_FileNameInText  = "/@([a-zA-Z0-9]+)/"; // Group #1 is the file name 
$ReplaceFunction_ByFileName = "ReplaceByFileContent"; 
function ReplaceByFileContent($Match) { 
    $FileName = GetGroupMatchText($Match, 1);  // Group # is the gile name 

    // $FileContent = get_file_content($FileName); // Get the content of the file 
    $FileContent = "{@ content of: $FileName}"; // Dummy content for testing 

    return $FileContent; // Returns the replacement 
} 

// Main -------------------------------------------------------------------------------------------- 

$Text = " === @file1 ~ @file2 === "; 
echo ReplaceAll($RegEx_FileNameInText, $ReplaceFunction_ByFileName, $Text); 

Ceci va afficher === {@ content of: file1} ~ {@ content of: file2} ===.

Le programme remplacera toute la correspondance regex avec le remplacement renvoyé du résultat du nom de la fonction donnée. Dans ce cas, la fonction de rappel est ReplaceByFileContent dans laquelle le nom de fichier est extrait du groupe # 1 dans la regex. Je crois que mon code est auto-documenté mais si vous avez des questions, vous pouvez me le demander.

Hope I aide.

+0

wow quelle excellente réponse, merci! – Johannes

2

PHP fonctions natives str_pos et str_replace sont mieux à utiliser lorsque vous recherchez à travers des fichiers ou des chaînes plus volumineux. ;)

+0

str_pos n'aidera pas quand il y a beaucoup d'occurrences de @? – Johannes

1

propre Beaucoup:

<?php 

$content = file_get_content('content.txt'); 
$m = array(); 
preg_match_all('`@([^\s]*)(\s|\Z)`ism', $content, $m, PREG_SET_ORDER); 
foreach($m as $match){ 
    $innerContent = file_get_contents($match[1]); 
    $content = str_replace('@'.$match[1], $innerContent, $content); 
} 
// done! 

?> 

regex testé avec: http://www.spaweditor.com/scripts/regex/index.php

+0

merci! mais il doit être programmé, de sorte qu'il regarde par fichier2 sans savoir quels fichiers concaténer avant qu'il ait traversé toutes les occurrences d'un @ :) – Johannes

+0

bien l'exemple donné et votre poste n'a pas mentionné plusieurs occurrences de @. laisse moi mettre à jour. – mauris

+0

Eh bien, voici un meilleur qui est beaucoup plus propre. il détectera de @ à un caractère espace, EOL ou fin de texte. – mauris

Questions connexes