2016-08-02 5 views
5

Datei zu lesen ich diese Regex mit mehreren Online-Tools entwickelt haben und mit Hilfe der Community:Valid RegEx nach Online-Test-Tools, keine passenden Ergebnisse bekommen, wenn in Browser

https://regex101.com/r/hJ4pD5/1

(\s[A-Z]\.).+?(?=(\s[A-Z]\.)|(\W?(Answer:)\W?)) 

Die Ziel ist es, alle Alternativen zu einer Frage zu extrahieren. Nach regexr und regex101 dies eine gültige Javascript regex, die gut mit dem test data(pastebin) funktioniert:

1. Question goes here: 
A. Answer one 
B. Answer two 
C. Answer three D. Not indented Answer 
Answer: B is correct 

Erwartete Matches sein sollte:

"A. Antwort ein", "B. zwei Antwort", "C. Antwort drei", "D. Nicht eingerückte Antwort"

Aber wenn ich es im Code implementieren, führt dies nicht sehr gut, keine Übereinstimmungen gefunden.

(Versuchen Sie es mit den Pastebin Daten)

/** 
* Created by Schwusch on 01/08/2016. 
*/ 
$(document).ready(start); 
var questionsRaw; 
var questionsFormatted = []; 
var questionIndex = 0; 

function readSingleFile(e) { 
    var file = e.target.files[0]; 
    if (!file) { 
     return; 
    } 
    var reader = new FileReader(); 
    reader.onload = function(e) { 
     var contents = e.target.result; 
     displayContents(contents); 
    }; 
    reader.readAsText(file); 
} 
/* REGEX MAGIC -------------------------------------------------*/ 
function displayContents(contents) { 
    questionsRaw = contents.split('---'); 
    $.each(questionsRaw, function(index, question) { 
     var answer = question.split("Answer:")[1]; 
     var splittedQuestion = question.split("A.")[0]; 
     var alternatives = question.match(/(\s[A-Z]\.).+?(?=(\s[A-Z]\.)|(\W?(Answer:)\W?))/g); 
     questionsFormatted.push({ 
      question: splittedQuestion, 
      alternatives: alternatives, 
      answer: answer 
     }); 
    }); 
/* END REGEX MAGIC -------------------------------------------------*/ 
    var element = document.getElementById('file-content'); 
    element.innerHTML = questionsFormatted[questionIndex].question; 
    for (var i = 0; i < questionsFormatted[questionIndex].alternatives.length ; i++) { 
     $('#alternatives').append('<button type="button" class="list-group-item">' + questionsFormatted[questionIndex].alternatives[i] + '</button>'); 
    } 
} 
function start() { 
    document.getElementById('file-input') 
     .addEventListener('change', readSingleFile, false); 

    $(window).keydown(function(e) { 
     e = e || event; 
     switch(e.keyCode) { 
      case 37: // left 
       previousQuestion(); 
       return false; 
      case 38: // up 
       showQuestion(); 
       return false; 
      case 39: // right 
       nextQuestion(); 
       return false; 
      case 40: // down 
       showAnswer(); 
       return false; 
     } 
    }); 
    $(document).on('change', ':file', function() { 
     var input = $(this), 
      numFiles = input.get(0).files ? input.get(0).files.length : 1, 
      label = input.val().replace(/\\/g, '/').replace(/.*\//, ''); 
     input.trigger('fileselect', [numFiles, label]); 
    }); 

    $(':file').on('fileselect', function(event, numFiles, label) { 
     var element = document.getElementById('filechoose'); 
     element.innerHTML = label; 
    }); 
} 

function showAnswer() { 
    var element = document.getElementById('file-content'); 
    element.innerHTML = questionsFormatted[questionIndex].answer; 
} 

function showQuestion() { 
    var element = document.getElementById('file-content'); 
    element.innerHTML = questionsFormatted[questionIndex].question; 
} 

function nextQuestion() { 
    if (questionIndex < questionsFormatted.length - 1) questionIndex++ ; 
    else questionIndex = 0; 
    var element = document.getElementById('file-content'); 
    element.innerHTML = questionsFormatted[questionIndex].question; 
    $(".list-group-item").remove(); 
    for (var i = 0; i < questionsFormatted[questionIndex].alternatives.length ; i++) { 
     $('#alternatives').append('<button type="button" class="list-group-item">' + questionsFormatted[questionIndex].alternatives[i] + '</button>'); 
    } 
} 

function previousQuestion() { 
    if (questionIndex > 0) questionIndex-- ; 
    else questionIndex = questionsFormatted.length - 1; 
    var element = document.getElementById('file-content'); 
    element.innerHTML = questionsFormatted[questionIndex].question; 
    $(".list-group-item").remove(); 
    for (var i = 0; i < questionsFormatted[questionIndex].alternatives.length ; i++) { 
     $('#alternatives').append('<button type="button" class="list-group-item">' + questionsFormatted[questionIndex].alternatives[i] + '</button>'); 
    } 
} 
<!DOCTYPE html> 
<html lang="en"> 
<head> 
    <meta charset="UTF-8"> 
    <title>Question tool</title> 
    <script src="https://code.jquery.com/jquery-3.1.0.js" 
      integrity="sha256-slogkvB1K3VOkzAI8QITxV3VzpOnkeNVsKvtkYLMjfk=" crossorigin="anonymous"></script> 

    <!-- Latest compiled and minified CSS --> 
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" 
      integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> 

    <!-- Optional theme --> 
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" 
      integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous"> 
    <script src="script.js"></script> 
    <style> 
     /* Move down content */ 
     body { 
      padding-top: 20px; 
      padding-bottom: 20px; 
     } 

    </style> 
</head> 
<body> 

<div> 
    <div class="container"> 

     <div class="jumbotron"> 
      <h3>Question Tool</h3> 
      <label class="btn btn-default btn-file" id="filechoose"> 
       Choose File 
       <input type="file" id="file-input" style="display: none;"/> 
      </label> 
      <div class="btn-group btn-group-justified" role="group" aria-label="..."> 
       <div class="btn-group" role="group"> 
        <button type="button" class="btn btn-lg btn-primary" onclick="showAnswer()" role="button"> 
         <span class="glyphicon glyphicon-arrow-down" aria-hidden="true"></span>Show Answer 
        </button> 
       </div> 
       <div class="btn-group" role="group"> 
        <button type="button" class="btn btn-lg btn-success" onclick="showQuestion()" role="button"> 
         <span class="glyphicon glyphicon-arrow-up" aria-hidden="true"></span>Show Question 
        </button> 
       </div> 
       <div class="btn-group" role="group"> 
        <button type="button" class="btn btn-lg btn-danger" onclick="previousQuestion()" role="button"> 
         <span class="glyphicon glyphicon-arrow-left" aria-hidden="true"></span>Previous Question 
        </button> 
       </div> 
       <div class="btn-group" role="group"> 
        <button type="button" class="btn btn-lg btn-info" onclick="nextQuestion()" role="button"> 
         <span class="glyphicon glyphicon-arrow-right" aria-hidden="true"></span>Next Question 
        </button> 
       </div> 
      </div> 

      <div id="file-content" class="well"></div> 
      <div id="alternatives" class="list-group"> 
      </div> 
     </div> 

    </div> 
</div> 

</body> 
</html> 

Warum ist es in der Online-Tester arbeiten, aber nicht in einem Browser?

+0

Ich kann Ihr Snippet wegen anderer Probleme nicht ausführen, aber die Regex funktioniert gut in der Konsole meines Browsers (obwohl mit jedem Match Leerzeichen abgeschnitten werden müssen) – moopet

+0

Der Titel ist nicht korrekt formuliert, die Regex ist gültig aber hat keine Übereinstimmungen bekommen. Danke für deine Mühe. – Schwusch

Antwort

5

Der Grund, warum es für Sie nicht funktioniert, ist, dass im Gegensatz zu dem Text, den Sie während Ihrer Tests auf regex101.com verwendet haben, die Datei \r\n als Newline-Sequenz statt nur \n verwendet.

Dazu kommt, dass die . Meta-Zeichen nicht standardmäßig \r entspricht, und dass JavaScript, um die s Modifikator nicht unterstützt, die dieses Verhalten ändern könnte, erhalten Sie weniger oder gar keine Spiele.

Konkreter: im regulären Ausdruck der Teil .+? wird die übereinstimmenden Zeichen zu stoppen, wenn es die \r trifft. Zuerst tut es dies, weil es nach vorne schaut und feststellt, dass es die \r entweder mit \s oder \W übereinstimmen kann, aber die nächste \n stimmt weder mit [A-Z] noch mit der A von Answer: überein. So Backtracks und versucht, mit dem .+? Teil fortzufahren, aber das schlägt auch fehl, weil \r nicht mit dem wie oben erklärt übereinstimmen kann. Der Matching-Prozess beginnt also wieder am Anfang des regulären Ausdrucks, um eine mögliche nächste Übereinstimmung zu finden. Und das scheitert immer wieder an den gleichen Gründen.

Um dies zu beheben, zwei Dinge ändern:

  • ein + nach den \s in der Mitte hinzufügen, so wird es die \n nicht nur entsprechen, sondern die vorhergehende \r auch.

  • ändern \W? zu \W*, also wieder, kann es die vorangehenden als auch \r entsprechen.

Dies sollte funktionieren:

/(\s[A-Z]\.).+?(?=(\s+[A-Z]\.)|(\W*(Answer:)\W?))/g 

Während dies es löst, würde ich vorschlagen, auch diesen regex zu vereinfachen weiter:

/\s[A-Z]\..+?(?=\s+[A-Z]\.|\W*Answer:)/g 

Vor allem die \W? am Ende macht wenig Sinn : es entspricht entweder \W oder nicht, und in beiden Fällen akzeptieren Sie es.

+0

Das ist sehr konstruktiv und informativ, danke. Ist '\ r \ n \ 'in Textdateien üblich, aber nicht in Feldern wie Textareas? Oder gibt es einen anderen Grund, warum es anders ist? – Schwusch

+1

Der Standard [Newline Sequenz] (https://en.wikipedia.org/wiki/Newline#Representations) in Dateien hängt von dem Betriebssystem ab, auf dem Sie sich befinden: Windows verwendet '\ r \ n', Unix basierte Systeme meistens' \ n'. In Browsern liefert das DOM meistens Inhalte mit '\ n'-Zeilenumbrüchen, unabhängig vom Betriebssystem, auf dem sie laufen. Der Grund für die Unterschiede ist ein [historischer] (https://en.wikipedia.org/wiki/Newline#Representations#History). – trincot

Verwandte Themen