2012-04-14 15 views
-1

Ich habe eine harte Zeit mit dem folgenden;Multiline Regex ersetzen, wenn mehr als zwei

Es gibt eine Word-Datei mit Fragen und Antworten, die ich in Moodle (Online-Frageseite) in einem bestimmten Format importieren muss. Alles ist schwarz für die richtigen Antworten, diese sind grün. Das Startformat ist folgende:

1. Question example 

a. Wrong 

b. Wrong 

C. Wrong 

D. Right 

Der Ausgang

:Question example 

:Question example 

{ 

~ Wrong 

~ Wrong 

~ Wrong 

= Right 

} 

ich die Datei öffnen werden soll alle roten Absatzmarken in Wort ersetzen (ich kann ein mit Gruppen nicht ersetzen) mit *. Danach exportiere ich die .docx Datei in Text. Öffnen Sie auf meinem Linux-Computer und werfen Sie den folgenden Regex darauf.

sed -i -e 's/^\r/\n/g' tmp #OS X white line replacement      
sed -i -e 's/\r//g' tmp #remove white lines       
sed -i -e 's:^[a-z]\.:~:' tmp #Replace Leading question letters with tilde                        
sed -i -e 's/\(^[0-9]*\.\ \)\(.*\)/}\n::\2\n::\2\n{/' tmp #regenerate tittle      
sed -i -n '${p;q};N;/\n\*/{s/"\?\n//p;b};P;D' tmp #next line starts with * append to front of current                
sed -i -e 's:^~\(.*\)\(\*.*\)$:=\1:' tmp #move * from back to = to front 
sed -i -e 's:^\*:=:' tmp #replace any remaining * with =   
sed '/^$/d' tmp #delete any remaining white lines 

Dies ist nicht groß, aber gut funktioniert, Fragen sind handgefertigt und haben viele Fehler, so muss ich noch diese von Hand zu Fuß Trog. Der schwierige Teil ist, wenn ich mehrere richtige Antworten habe. Die Ausgabe sollte wie folgt aussehen;

:Question example 

:Question example 

{ 

~%-100% Wrong 

~%-100% Wrong 

~%50% Right 

~%50% Right 

} 

Idealerweise habe ich einen sed oder perl regex, dass die Menge von = zählt singt zwischen {und ersetzt sie durch ~% 50%. Und das alles mit% -100%. Ich kann diesen Code auch für 3 richtige Antworten haben, wobei jede richtige Antwort ~% 33% wird.

Ist das machbar? Ich habe über 1000 Fragen und es würde sicher helfen, dies zu automatisieren. Multiline-Ersatz mit sed ist mit zwei Zeilen ziemlich schwierig, also denke ich, vier oder mehr Zeilen brauchen Perl? Ich habe keine Erfahrung in Perl.

Könnte mir jemand mit diesem helfen? Bitte entschuldigen Sie mein schlechtes Englisch Ich bin ein Nicht-Muttersprachler.

+0

Suchen Sie sed halten Raum Operationen; es scheint schwierig, aber ich denke, es ist möglich, diese zu verwenden. –

+0

Was machst du mit den verschiedenen Zeilenumbrüchen zwischen Windows und Linux? Und was ist mit all den Zeichen, die Word für Sie "korrigiert", wie Zitate? – stark

+0

Es würde Ihnen sehr helfen, wenn Sie Beispiele aus der Praxis zeigen würden. Es ist schwer aus Ihrem Beispiel zu erkennen, welcher Text real ist und welcher Platzhalter ist. Erscheint 'Falsch' und' Rechts' in der Quelldatei? Wenn ja, wie kann man sagen, welche Antworten richtig und welche falsch sind? Wenn nicht, worauf kommt es in der Ausgabedatei an? – Borodin

Antwort

1
my $file = do { local $/; <> }; 
my @questions = split /(?<=.)(?=[0-9]+\.)/s, $file; 
for (@questions) { 
    my @lines = split /^/m; 

    my $title = shift(@lines); 
    $title =~ s/^\S+\s*/:/; 

    my $num_right; 
    my $num_wrong; 
    for (@lines) { 
     if (/Right/) { ++$num_right; } 
     elsif (/Wrong/) { ++$num_wrong; } 
    } 

    my $num_answers = $num_right + $num_wrong; 

    my $right_pct = sprintf('%.0f', $num_right/$num_answers*100); 
    my $right_prefix = $num_right == 1 ? "=" : "~%$right_pct%"; 
    my $wrong_prefix = $num_right == 1 ? "~" : "~%-100%"; 

    for (@lines) { 
     if (/Right/) { s/^\S+/$right_prefix/; } 
     elsif (/Wrong/) { s/^\S+/$wrong_prefix/; } 
    } 

    print(
     $title, 
     "\n", 
     $title, 
     "\n{\n", 
     @lines, 
     "\n}\n", 
    ); 
} 

ersetzen /Right/ und /Wrong/ mit etwas angemessen.

+0

Nach der Bearbeitung haben Sie ein fehlendes ',' nach dem ersten Zeilenumbruch in der 'print' Anweisung eingefügt. Und der bedingte Operator sollte '$ num_right' anstelle von' $ num_wrong' verwenden, wenn er die Präfixe bestimmt. – Borodin

+0

Fest, danke .. – ikegami

1

Das folgende Programm funktioniert nach meiner besten Schätzung, was Sie brauchen. Es funktioniert, indem alle Informationen in ein Array gelesen und dann formatiert werden.

Wie es steht, werden die Daten in die Quelle integriert und aus dem Dateihandle DATA gelesen. Durch Ändern der Schleife in while (<>) { ... } können Sie eine Datendatei in der Befehlszeile angeben.

Sie müssen mich korrigieren, wenn meine Vermutungen falsch sind.

use strict; 
use warnings; 

my @questions; 

while (<DATA>) { 
    next unless /\S/; 
    s/\s+$//; 
    if (/^\d+\.\s*(.+)/) { 
    push @questions, [$1]; 
    } 
    elsif (/^[A-Za-z]\.\s*(.+)/i) { 
    push @{$questions[-1]}, $1; 
    } 
} 

for my $question (@questions) { 

    my ($text, @answers) = @$question; 

    print "::$text\n" for 1, 2; 

    my $correct = grep /right/i, @answers; 
    my $percent = int(100/$correct); 

    print "{\n"; 

    if ($correct == 1) { 
    printf "%s %s\n", /right/i ? '=' : '~', $_ for @answers; 
    } 
    else { 
    my $percent = int(100/$correct); 
    printf "~%%%d%%~ %s\n", /right/i ? $percent : -100, $_ for @answers; 
    } 

    print "}\n"; 
} 

__DATA__ 
1. Question one 

a. Wrong 

b. Wrong 

c. Right 

d. Wrong 

2. Question two 

a. Right 

b. Wrong 

c. Right 

d. Wrong 

3. Question three 

a. Right 

b. Right 

c. Wrong 

d. Right 

Ausgang

::Question one 
::Question one 
{ 
~ Wrong 
~ Wrong 
= Right 
~ Wrong 
} 
::Question two 
::Question two 
{ 
~%50%~ Right 
~%-100%~ Wrong 
~%50%~ Right 
~%-100%~ Wrong 
} 
::Question three 
::Question three 
{ 
~%33%~ Right 
~%33%~ Right 
~%-100%~ Wrong 
~%33%~ Right 
} 
1

Dies könnte für Sie arbeiten:

cat <<\! >file.sed 
> # On encountering a digit in the first character position 
> /^[0-9]/{ 
> # Create a label to cater for last line processing 
> :end 
> # Swap to hold space 
> x 
> # Check hold space for contents. 
> # If none delete it and begin a new cycle 
> # This is to cater for the first question line 
> /./!d 
> # Remove any carriage returns 
> s/\r//g 
> # Remove any blank lines 
> s/\n\n*/\n/g 
> # Double the question line, replacing the question number by a ':' 
> # Also append a { followed by a newline 
> s/^[0-9]*\.\([^\n]*\n\)/:\1:\1{\n/ 
> # Coalesce lines beginning with a * and remove optional preceeding " 
> s/"\?\n\*/*/g 
> # Replace the wrong answers a,b,c... with ~%-100% 
> s/\n[a-zA-z]*\. \(Wrong\)/\n~%-100% \1/g 
> # Replace the right answers a,B,c... with ~%100% 
> s/\n[a-zA-Z]*\. \(Right\)/\n~%100% \1/g 
> # Assuming no more than 4 answers: 
> # Replace 4 correct answers prefix with ~%25% 
> s/\(~%100%\)\(.*\)\1\(.*\)\1\(.*\)\1/~%25%\2~%25%\3~%25%\4~%25%/ 
> # Replace 3 correct answers prefix with ~%33% 
> s/\(~%100%\)\(.*\)\1\(.*\)\1/~%33%\2~%33%\3~%33%/ 
> # Replace 2 correct answers prefix with ~%50% 
> s/\(~%100%\)\(.*\)\1/~%50%\2~%50%/ 
> # Append a newline and a } 
> s/$/\n}/ 
> # Break and so print newly formatted string 
> b 
> } 
> # Append pattern space to hold space 
> H 
> # On last line jump to end label 
> $b end 
> # Delete all lines from pattern space 
> d 
> ! 

Dann laufen:

sed -f file.sed file 
0

Ihre Beispiele dieses Dokument nicht überein ation: http://docs.moodle.org/22/en/GIFT.Fragen Titel und questiosn werden durch zwei Doppelpunkte begrenzt nicht ein Doppelpunkt:

//Comment line 
::Question title 
:: Question { 
=A correct answer 
~Wrong answer1 
#A response to wrong answer1 
~Wrong answer2 
#A response to wrong answer2 
~Wrong answer3 
#A response to wrong answer3 
~Wrong answer4 
#A response to wrong answer4 
} 

Einige Leute gab ihre naiven Antworten auf der Grundlage Ihrer Beispiele statt die realen spec zu finden, oops.

Ihre Frage kann nicht beantwortet werden, weil Ihr Format nicht die richtigen Antworten anzeigt. Das heißt:

1. Question 

a. Is this right? 

b. Or this? 

c. Or this? 

Sie sagen, dass diese identifiziert Farben im ursprünglichen Word-Dokument verwenden und dass Sie tun einigen Ersatz an, dass die Informationen zu erhalten; Sie zeigen jedoch kein Beispiel dafür! Hoppla ...