ما هي أفضل طريقة لتحليل الجسم من النص ضد متعددة (15+) regexes على كل سطر ؟

StackOverflow https://stackoverflow.com/questions/303830

سؤال

لدي مجموعة من النصوص التي يجب أن مسح كل سطر يحتوي على ما لا يقل عن 2 و أحيانا أربعة أجزاء من المعلومات.المشكلة هي أن كل خط يمكن أن يكون 1 من 15-20 إجراءات مختلفة.

في روبي القانون الحالي تبدو إلى حد ما مثل هذا:

text.split("\n").each do |line|  #around 20 times..

..............

      expressions['actions'].each do |pat, reg| #around 20 times

.................

ومن الواضح أن 'المشكلة'.لم يتمكن من جعله أسرع (في C++ بنسبة 50% هامش) عن طريق الجمع بين كل regexen إلى واحد ولكن هذا لا يزال لا سرعة لا تتطلب -- لا تحتاج إلى تحليل الآلاف من هذه الملفات بسرعة!

الآن أنا مطابقتها مع regexes -- ولكن هذا لا يطاق بطيئة.لقد بدأت مع روبي وقفز إلى C++ أملا في أن أحصل على زيادة السرعة و انها مجرد لا يحدث.

لقد عرضا قراءة على أوتاد والنحوي على أساس تحليل ولكن يبدو إلى حد ما صعبة التنفيذ.هذا هو الاتجاه الذي يجب أن الرأس أو هل هناك طرق مختلفة?

أساسا أنا تحليل البوكر ناحية تاريخها و كل سطر من ناحية التاريخ عادة ما تحتوي على 2-3 قطع من المعلومات التي كنت بحاجة لجمع:الذين لاعب كان, كم من المال أو ما بطاقات العمل ينطوي..الخ..

عينة النص الذي يحتاج إلى تحليل:

buriedtens posts $5
The button is in seat #4
*** HOLE CARDS ***
Dealt to Mayhem 31337 [8s Ad]
Sherwin7 folds
OneMiKeee folds
syhg99 calls $5
buriedtens raises to $10

بعد جمع هذه المعلومات كل عمل هو تحول إلى عقدة xml.

إن روبي تنفيذ هذا أسرع بكثير من بلدي C++ واحد ولكن هذا غالبا.فقط لأني لم أكتب في التعليمات البرمجية c لأكثر من 4-5 سنوات

تحديث: أنا لا أريد أن وظيفة كل رمز هنا ولكن حتى الآن يدي/الثانية تبدو كما يلي:

588 hands/second -- boost::spirit in c++
60 hands/second -- 1 very long and complicated regex in c++ (all the regexen put together)
33 hands/second -- normal regex style in ruby

أنا حاليا اختبار antlr أن نرى إذا كان يمكننا أن نذهب أبعد من ذلك لكن الآن أنا سعيد جدا جدا مع الروح النتائج.

ذات السؤال: بكفاءة الاستعلام عن سلسلة واحدة متعددة regexes.

هل كانت مفيدة؟

المحلول

أود أن أقترح

حظا سعيدا

نصائح أخرى

دفعة.روح رائعة المكتبة التي تسمح لك لجعل مفصلة محلل تحليل و منذ محلل يتم إنشاؤها وتجميعها في التعليمات البرمجية الخاصة بك ، يجب أن يكون أسرع بكثير حيوي-احتساب الحل.بناء الجملة هو الغالب يتم ذلك مع قوالب التعبير (مصطلح الكثير من طاقتها المشغلين) ، مما يعني أنك في الواقع يكتب لهم الحق في التعليمات البرمجية الخاصة بك.

هنا هو طريقة واحدة لفعل ذلك ، إذا كنت تستخدم بيرل.
نسخ من perldoc perlfaq6

while (<>) {
    chomp;
    PARSER: {
        m/ \G( \d+\b    )/gcx   && do { print "number: $1\n";  redo; };
        m/ \G( \w+      )/gcx   && do { print "word:   $1\n";  redo; };
        m/ \G( \s+      )/gcx   && do { print "space:  $1\n";  redo; };
        m/ \G( [^\w\d]+ )/gcx   && do { print "other:  $1\n";  redo; };
    }
}

لكل خط ، PARSER الحلقة الأولى يحاول تطابق سلسلة الأرقام تليها كلمة الحدود.هذه المباراة يجب أن يبدأ في مكان آخر مباراة تركته (أو بداية السلسلة في أول مباراة).منذ m/ \G( \d+\b )/gcx يستخدم c العلم, إذا كانت السلسلة لا يتطابق مع التعبير العادي, perl لا إعادة تعيين pos() و المباراة القادمة يبدأ في نفس الموقف في محاولة نمط مختلف.

انظر مطابقة التعبير العادي يمكن أن تكون بسيطة وسريعة (ولكن بطيئة في Java, Perl, PHP, Python, Ruby, ...).اعتمادا على حجم البيانات وكيفية المعقدة الخاصة بك باستخدام التعابير المنطقية هي أن الأمر قد يكون مجرد أسرع إلى الكتابة الخاصة بك تحليل المنطق.

لقد عرضا قراءة على أوتاد والنحوي على أساس تحليل ولكن يبدو إلى حد ما صعبة التنفيذ.هذا هو الاتجاه الذي يجب أن الرأس أو هل هناك طرق مختلفة?

شخصيا لقد نمت الى الحب أوتاد.وسوف ربما يستغرق قليلا للحصول على راحة معهم ، ومع ذلك أعتقد أنهم أكثر من ذلك بكثير للصيانة أنه واضحة الفوز.أجد تحليل شفرة المصدر من الكثير من الأخطاء غير متوقعة كما تجد حافة جديدة الحالات في المدخلات.التعريفي قواعد النحو مع nonterminals أسهل بالنسبة لي أن التحديث عندما يحدث هذا بالمقارنة مع حلقة والاحكام الثقيلة regex رمز.تسمية قوية.

في روبي هناك الشجرة وهو محلل مولد يستخدم أوتاد.لقد وجدت مؤخرا أنه لطيف جدا في استبدال regex اليد الثقيلة كتب محلل مع قواعد اللغة.

هل التعبير العادي مباريات هذا التداخل ؟ هذا هو عندما اثنين أو أكثر من regexes تطابق نفس الخط ، أنها لا تتطابق دائما مع أجزاء مختلفة من الخط (أي تداخل)?

إذا كان يطابق أبدا التداخل تشغيل البحث الخاص بك باستخدام أحد العادية التعبير الذي يجمع بين 15 regexes لديك الآن:

regex1|regex2|regex3|...|regex15

استخدام التقاط مجموعات إذا كنت بحاجة إلى أن تكون قادرة على تحديد أي من 15 regexes مطابقة.

البحث عن البيانات الخاصة بك مرة واحدة لمدة طويلة regex سوف يكون أسرع من البحث في ذلك 15 مرة.كيف أسرع بكثير يعتمد على regex المحرك الذي تستخدمه و تعقيد التعبيرات العادية.

محاولة اختبار بسيط في بيرل.قرأت عن "دراسة" وظيفة.ما قد حاول هو:

  • قراءة الملف بأكمله أو عدد كبير من الخطوط إذا كانت هذه الملفات كبيرة جدا في سلسلة واحدة
  • إضافة رقم السطر إلى بداية كل سطر كما تذهب.
  • "دراسة" سلسلة.هذا يبني جدول بحث بواسطة الحرف ، يمكن أن تكون كبيرة.
  • تشغيل التعبير العادي مباريات على السلسلة ، يحدها من قبل أسطر (استخدام m و s regex المعدلات).التعبير يجب استخراج رقم السطر جنبا إلى جنب مع البيانات.
  • تعيين مجموعة البند فهرستها من قبل عدد خط إلى البيانات الموجودة على هذا الخط ، أو فعل شيء حتى أكثر ذكاء.
  • أخيرا يمكنك معالجة البيانات المخزنة في صفيف.

لم أحاول ذلك ، ولكن قد يكون من المثير للاهتمام.

فكرة أخرى إذا كان لديك انيق رباعية أو oct الأساسية server لاستخدام هذا.

بناء وتجهيز خط الأنابيب الذي يقسم العمل.المرحلة الأولى يمكن أن تقطع الملفات في لعبة واحدة أو يد كل منهما ، ثم كتابة كل واحدة إلى واحدة من ثمانية المرحلة الثانية الأنابيب التي تقرأ البيانات العملية و تنتج الانتاج بطريقة أو بأخرى ، وربما إلى قاعدة البيانات على جهاز آخر.

في تجربتي هذه الأنابيب عملية متعددة التصاميم ما يقرب من أسرع و أسهل بكثير من التصحيح من خيوط متعددة التصاميم.كما أنه سيكون من السهل اقامة مجموعة من الآلات باستخدام مآخذ الشبكة بدلا من الأنابيب.

حسنا, هذا يجعل الأمور أكثر وضوحا (البوكر اليد وتاريخها).أعتقد أن كنت صنع أداة الإحصاءات (العدوان عامل ، وذهب إلى المواجهة ، طوعا ضعي في وعاء.... الخ).أنا لست متأكدا لماذا تحتاج سرعة المفرطة من أجل ذلك ؛ حتى لو كنت multitabling مع 16 الجداول اليدين فقط دغدغة في بسعر معتدل.

أنا لا أعرف روبي, ولكن في بيرل كنت تفعل قليلا بيان التبديل في نفس الوقت الحصول على أجزاء كبيرة في $1, $2 الخ..في تجربتي, هذا ليس أبطأ من إجراء مقارنات السلسلة ثم تقسيم الخط مع غيرها من الوسائل.

HAND_LINE: for ($Line)
    { /^\*\*\* ([A-Z ]+)/ and do 
        { # parse the string that is captured in $1
          last HAND_LINE; };
      /^Dealt to (.+) \[(.. ..)\]$/ and do
        { # $1 contains the name, $2 contains the cards as string
          last HAND_LINE; };
      /(.+) folds$/ and do
        { # you get the drift
          last HAND_LINE; }; };

أنا لا أعتقد أن كنت حقا يمكن أن تجعل من أسرع.وضع الشيكات الخطوط التي تحدث أكثر في المركز الأول (على الأرجح أضعاف البيانات) و تلك التي تحدث أحيانا في الماضي (بداية جديدة من ناحية ، "*** NEXT PHASE ***").

إذا كنت تجد أن الملف الفعلي القراءة هي عنق الزجاجة ، يمكنك ربما نلقي نظرة على ما الوحدات التي يمكن استخدامها لمعالجة الملفات الكبيرة;على بيرل ، Tie::File يتبادر إلى الذهن.

تأكد من أن تقرأ كل جهة مرة واحدة فقط.لا قراءة جميع البيانات مرة أخرى بعد كل ناحية ، بدلا من ذلك نأخذ على سبيل المثالجدول تجزئة اليد معرفات بالفعل تحليل.

في مثل هذا, أنا فقط أغمض عيني و استخدام Lexer+محلل مولد.يمكنك التغلب على ذلك مع اليد الأمثل ربما ، لكنه أسهل بكثير لاستخدام المولدات.كما أنها طريقة أكثر مرونة عند المدخل يتغير فجأة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top