用正则表达式C#怎么把题目内所有的信息都提取出来变成表格形式的内容啊?

50题目:.给病鸡更换胃管,要求 答案:D
A:.每天更换,晚上拔管,次晨插管
B:.每周更换,晚上拔管,次晨插管
C:.每周更换,上午拔管,晚上插管
D:.每天更换,上午拔管,晚上插管

100题目:.呼吸增快常见于 症状 答案:E
A:.发烧
B:.颅内疾病
C:.安眠药中毒
D:.呼吸中枢衰竭
E:.老年人

120题目:.你的姓名是 。 答案:E
A:.qd
B:.qod
C:.qn
D:.biw
E:.Hs
我想把以上三道题用正则表达式的方式换成表格形式显示,不知道怎么写啊,请大神们帮忙!

题目答案A答案B答案C答案D答案E答案F答案H正确答案
给病鸡更换胃管,要求每天更换,晚上拔管,次晨插管每周更换,晚上拔管,次晨插管每周更换,上午拔管,晚上插管每天更换,上午拔管,晚上插管 D
呼吸增快常见于 症状发烧颅内疾病安眠药中毒呼吸中枢衰竭老年人 E
你的姓名是 。qdqodqnbiwHs E

像这种正则表达式应该怎么写啊?

阅读 2.5k
4 个回答

Lexer.cs

using System.Collections.Generic;

namespace Test
{
    public class Lexer
    {
        private string mSource;
        private int mCurrent = 0;
        private int mStart = 0;
        private char Advance() => mSource[mCurrent++];
        private bool IsAtEnd() => mCurrent >= mSource.Length;
        private bool IsDigit(char c) => c >= '0' && c <= '9';
        private bool IsAlpha(char c) => (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');

        private List<string> mTokens = new();

        private char Look() => IsAtEnd() ? '\0' : mSource[mCurrent];
        private char LookAhead()
        {
            if (mCurrent + 1 >= mSource.Length) return '\0';
            return mSource[mCurrent + 1];
        }
        private void ReadTopic()
        {
            while (Look() != ':') Advance();
            AddToken('=');
        }

        private void ReadString()
        {
            while (Look() != '\r' && Look() != '\n' && !IsAtEnd() && !(Look() == ' ' && LookAhead() == '答'))  Advance();
            AddToken();
        }

        private bool Match(char expected)
        {
            if (IsAtEnd()) return false;
            if (mSource[mCurrent] != expected) return false;
            mCurrent++;
            return true;
        }

        private void ReadToken()
        {
            mStart = mCurrent;
            var c = Advance();
            switch (c)
            {
                case ':':
                case ':':
                case '.':
                case ' ':
                    {
                        AddToken(c);
                        break;
                    }
                case '\r':
                case '\n':
                    break;
                case '答':
                    {
                        if (Match('案')) AddToken();
                        break;
                    }
                default:
                    if (IsDigit(c))
                    {
                        ReadTopic();
                    }
                    else if (IsAlpha(c))
                    {
                        AddToken(c);
                    }
                    else
                    {
                        ReadString();
                    }
                    break;
            }

        }

        private void AddToken(char type) => mTokens.Add(type.ToString());
        private void AddToken()
        {
            string text = mSource.Substring(mStart, mCurrent - mStart);
            mTokens.Add(text);
        }

        public List<string> analyze(string source)
        {
            mSource = source;
            while (!IsAtEnd()) ReadToken();
            mTokens.Add("eof");
            return mTokens;
        }
    }
}

Parser.cs

using System;
using System.Collections.Generic;
using System.Text;

namespace Test
{
    public class Quiz
    {
        public string Subject { get; set; }
        public List<string> Options { get; set; } = new();
        public int Answer { get; set; }
        public override string ToString()
        {
            var sb = new StringBuilder();
            var index = 0;
            foreach (var item in Options)
            {
                sb.Append((char)('A' + index++));
                sb.Append(" ");
                sb.Append(item);
                sb.Append("\n");
            }
            return $"{Subject} 答案:{(char)('A' + Answer)}\n{sb}";
        }
    }

    public class Parser
    {
        private List<Quiz> mQuizzes = new();
        private List<string> mTokens;
        private int mCurrent = 0;
        private bool IsAtEnd() => Look() == "eof";

        private string Look() => mTokens[mCurrent];

        private string Advance()
        {
            if (!IsAtEnd()) mCurrent++;
            return mTokens[mCurrent - 1];
        }

        private bool Check(string type)
        {
            if (IsAtEnd()) return false;
            return Look() == type;
        }


        private bool Match(params string[] strs)
        {
            foreach (var type in strs)
            {
                if (Check(type))
                {
                    Advance();
                    return true;
                }
            }
            return false;
        }

        private Quiz ParseQuiz()
        {
            Quiz quiz = new();
            Match("=");
            Match(":");
            Match(".");
            quiz.Subject = Advance();
            Match(" ");
            Match("答案");
            Match(":");
            quiz.Answer = Char.Parse(Advance()) - 'A';
            while (!IsAtEnd() && !Check("="))
                quiz.Options.Add(ParseOption());
            return quiz;
        }

        private string ParseOption()
        {
            Advance();
            Match(":");
            Match(".");
            return Advance();
        }

        public List<Quiz> Parse(List<string> tokens)
        {
            mTokens = tokens;
            while (!IsAtEnd()) mQuizzes.Add(ParseQuiz());
            return mQuizzes;
        }
    }
}

使用

var source = @"50题目:.给病鸡更换胃管,要求 答案:D
A:.每天更换,晚上拔管,次晨插管
B:.每周更换,晚上拔管,次晨插管
C:.每周更换,上午拔管,晚上插管
D:.每天更换,上午拔管,晚上插管

100题目:.呼吸增快常见于 症状 答案:E
A:.发烧
B:.颅内疾病
C:.安眠药中毒
D:.呼吸中枢衰竭
E:.老年人";
var tokens = new Lexer().analyze(source);
var list = new Parser().Parse(tokens);
foreach(var item in list)
{
   Console.WriteLine(item.ToString());
}

感觉这个问题用正则来处理有点麻烦,也不适合用正则来处理。如果只是把这个文档转成表格的话,可以写个脚本来处理。

这个不完全能够用规则式处理,现在一般是AI技术来处理,因为题目形式太多变了,除非你能很规范的控制题目中题干、正确答案、备选项序和备选项内容直接的分隔符(这样的分隔符需要分层次,而且要极为特殊),否则直接用规则式来处理就是不可能完成的任务。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进