كيف يمكنني العثور على سلاسل التي تحتوي على غلاف مع بيرل؟

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

  •  18-09-2019
  •  | 
  •  

سؤال

أحاول تصفية الآلاف من الملفات، أبحث عن تلك التي تحتوي على ثوابت السلسلة مع حالة مختلطة. هذه السلاسل يمكن تضمينها في مساحة بيضاء، ولكنها قد لا تحتوي على مساحة بيضاء أنفسها. لذا فإن ما يلي (يحتوي UC Chars) مطابقات:

"  AString "   // leading and trailing spaces together allowed
"AString "     // trailing spaces allowed
"  AString"    // leading spaces allowed
"newString03"  // numeric chars allowed
"!stringBIG?"  // non-alphanumeric chars allowed
"R"            // Single UC is a match

ولكن هذه ليست:

"A String" // not a match because it contains an embedded space
"Foo bar baz" // does not match due to multiple whitespace interruptions
"a_string" // not a match because there are no UC chars

ما زلت أريد أن أتفق مع الخطوط التي تحتوي على حد سواء أنماط:

"ABigString", "a sentence fragment" // need to catch so I find the first case...

أريد استخدام بيرل Regexps، ويفضل أن يقودها ack. أداة سطر الأوامر. بوضوح، W. و W. لن تعمل. يبدو أن س يجب أن تطابق الأحرف غير الفضائية. لا يبدو لي أن أعرف كيفية تضمين متطلبات "حرف العلوي واحد على الأقل لكل سلسلة" ...

ack --match '\"\s*\S+\s*\"'

هو الأقرب الذي حصلت عليه. أحتاج إلى استبدال S +. مع شيئا ما التي تلتقط "حرف واحد على الأقل (ASCII) حرفا (في أي موضع لسلسلة غير بيضاء)".

هذا واضح في البرنامج في C / C ++ (ونعم، بيرل، من الناحية الإجرائية، دون اللجوء إلى Regexps)، أحاول فقط معرفة ما إذا كان هناك تعبير منتظم يمكن أن يفعل نفس الوظيفة.

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

المحلول

النمط التالي يمر جميع الاختبارات الخاصة بك:

qr/
  "      # leading single quote

  (?!    # filter out strings with internal spaces
     [^"]*   # zero or more non-quotes
     [^"\s]  # neither a quote nor whitespace
     \s+     # internal whitespace
     [^"\s]  # another non-quote, non-whitespace character
  )

  [^"]*  # zero or more non-quote characters
  [A-Z]  # at least one uppercase letter
  [^"]*  # followed by zero or more non-quotes
  "      # and finally the trailing quote
/x

باستخدام برنامج الاختبار هذا - الذي يستخدم النمط أعلاه دون /x وبالتالي بدون مسافة بيضاء وتعليقات - كمدخل إلى ack-grep (كما ack ويدعى أوبونتو)

#! /usr/bin/perl

my @tests = (
  [ q<"  AString ">   => 1 ],
  [ q<"AString ">     => 1 ],
  [ q<"  AString">    => 1 ],
  [ q<"newString03">  => 1 ],
  [ q<"!stringBIG?">  => 1 ],
  [ q<"R">            => 1 ],
  [ q<"A String">     => 0 ],
  [ q<"a_string">     => 0 ],
  [ q<"ABigString", "a sentence fragment"> => 1 ],
  [ q<"  a String  "> => 0 ],
  [ q<"Foo bar baz">  => 0 ],
);

my $pattern = qr/"(?![^"]*[^"\s]\s+[^"\s])[^"]*[A-Z][^"]*"/;
for (@tests) {
  my($str,$expectMatch) = @$_;
  my $matched = $str =~ /$pattern/;
  print +($matched xor $expectMatch) ? "FAIL" : "PASS",
        ": $str\n";
}

تنتج الناتج التالي:

$ ack-grep '"(?![^"]*[^"\s]\s+[^"\s])[^"]*[A-Z][^"]*"' try
  [ q<"  AString ">   => 1 ],
  [ q<"AString ">     => 1 ],
  [ q<"  AString">    => 1 ],
  [ q<"newString03">  => 1 ],
  [ q<"!stringBIG?">  => 1 ],
  [ q<"R">            => 1 ],
  [ q<"ABigString", "a sentence fragment"> => 1 ],
my $pattern = qr/"(?![^"]*[^"\s]\s+[^"\s])[^"]*[A-Z][^"]*"/;
  print +($matched xor $expectMatch) ? "FAIL" : "PASS",

مع قذيفة C والمشتقات، عليك الهروب من الانفجار:

% ack-grep '"(?\![^"]*[^"\s]\s+[^"\s])[^"]*[A-Z][^"]*"' ...

أتمنى أن أتمكن من الحفاظ على المباريات المميزة، لكن هذا لا يبدو أنه مسموح.

لاحظ أن نجا من اقتباسات مزدوجة (\") سوف تخلط بين هذا النمط بشدة.

نصائح أخرى

يمكنك إضافة متطلبات فئة حرف، مثل:

ack --match "\"\s*\S+[A-Z]\S+\s*\""

أنا أفترض أن ack يطابق سطر واحد في وقت واحد. ال \S+\s*\" جزء يمكن أن يطابق اقتباسات إغلاق متعددة على التوالي. سوف تتطابق مع مجمل "alfa"", ، بدلا من مجرد "alfa".

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