文字列からの情報抽出
Posted feedbacks - Flatten
Nested HiddenGaucheには名前付きサブマッチがあるんですが、これを解こうとしていてバグを見つけました。 (マッチしなかった名前付きサブマッチを問い合わせると#fではなく""が返ってしまう) というわけで普通にregexpを使った回答です。
1 2 3 4 5 6 7 | (define (pick string)
(cond
((#/([a-zA-Z]+)(-hidden)?(?:-(small|big))?\.([a-zA-Z]+)/ string)
=> (lambda (m)
(print "name: '"(m 1)"', ext: '"(m 4)"', size: "(or (m 3) "normal")
", hidden: "(if (m 2)"True" "False"))
(pick (m'after))))))
|
すみません、名前を付けた正規表現を知らないので、とりあえず普通の正規表現で。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | import re
def extract(s):
for m in re.finditer('([a-zA-Z]+)(-hidden)?(?:-(big|small))?\.([a-zA-Z]+)', s):
print "name:%r, ext:%r, size: %s hidden: %r" % \
(m.group(1), m.group(4), m.group(3) or "normal", bool(m.group(2)))
def main():
extract("""\
aaa abc-hidden.png>hoge-big.jpeg
---foo-hidden-small.gif|^_^a.bmp
--hiddena-hoge.png<=not hidden~~
--small.jpg<=not small(^_^)
normal-small-big.hoge""")
if __name__ == '__main__':
main()
|
やはり一番乗りは無理ですね…… 出力結果を示しておきます。 name:'abc', ext:'png', size: normal, hidden true name:'hoge', ext:'jpeg', size: big, hidden false name:'foo', ext:'gif', size: small, hidden true name:'a', ext:'bmp', size: normal, hidden false name:'hiddena', ext:'png', size: normal, hidden false name:'small', ext:'jpg', size: normal, hidden false name:'normal', ext:'hoge', size: big, hidden false #5行目がサンプル出力と異なるのはサンプル入力の問題と思われます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | import java.util.regex.*;
import java.util.*;
public class Sample {
private static final Pattern FILE_NAME_PATTERN = Pattern.
compile("¥¥b(¥¥p{Alpha}+)((¥¥-¥¥p{Alpha}+)*)¥¥.(¥¥p{Alpha}+)¥¥b");
public static void filter(String in) {
Matcher m = FILE_NAME_PATTERN.matcher(in);
while (m.find()) {
Set<String> attrSet= new HashSet<String>(Arrays.asList(m.group(2).
split("¥¥-")));
String size = "normal";
if (attrSet.contains("big")) {
size = "big";
} else if (attrSet.contains("small")) {
size = "small";
}
System.out.printf("name:'%s', ext:'%s', size: %s, hidden %b%n",
m.group(1), m.group(4), size, attrSet.contains("hidden"));
}
}
public static void main(String[] args) {
filter("aaa abc-hidden.png>hoge-big.jpeg¥n" +
"---foo-hidden-small.gif|^_^a.bmp¥n" +
"--hiddena-hoge.png<=not hidden‾‾¥n" +
"--small.jpg<=not small(^_^)¥n" +
"normal-small-big.hoge¥n");
}
}
|
いや、「特別な意味の-hidden, -small, -big以外でハイフンが使われることはない」から、5番目の出力は "hoge.png" で切れると解釈されると思います。
どうやら、問題の解釈を間違っていたようです。失礼しました。 題意に合うように訂正しました。
1 2 3 4 5 6 7 | diff 2522.java Sample.java
5,6c5,6
< private static final Pattern FILE_NAME_PATTERN = Pattern.
< compile("¥¥b(¥¥p{Alpha}+)((¥¥-¥¥p{Alpha}+)*)¥¥.(¥¥p{Alpha}+)¥¥b");
---
> private static final Pattern FILE_NAME_PATTERN = Pattern.compile(
> "¥¥b(¥¥p{Alpha}+)(((?:-hidden)|(?:-small)|(?:-big))*)¥¥.(¥¥p{Alpha}+)¥¥b");
|
これだと7番目もうまくいかないのでは?
(smallとbigが同時に出現しない、との制約から
nameがsmallである、と解釈される)
scanは強力無比
1 2 3 4 5 6 | def print_image_spec(str)
str.scan(/([A-Za-z]+)(-hidden)?(?:-(small|big))?\.([A-Za-z]+)/) do |name, hidden, size, ext|
printf("name:'%s', ext:'%s', size: %s hidden: %s\n",
name, ext, size||'normal', hidden ? 'True' : 'False')
end
end
|
名前つき正規表現なら、大体こんな感じになると思いますが、 このお題の「-hidden」の処理のように、なんらかの操作が 必要な場合は、ありがたみが少々落ちますね。
1 2 3 4 5 6 7 8 9 10 11 12 13 | import re
dat = '''aaa abc-hidden.png>hoge-big.jpeg
---foo-hidden-small.gif|^_^a.bmp
--hiddena-hoge.png<=not hidden~~
--small.jpg<=not small(^_^)
normal-small-big.hoge
'''
ptn = '(?P<name>[a-zA-Z]+)(-hidden)?(?:-(?P<size>big|small))?\.(?P<ext>[a-zA-Z]+)'
fmt = "name:'%(name)s', ext:'%(ext)s', size: %(size)s, hidden: %%s"
for g in re.finditer(ptn, dat):
print fmt % g.groupdict('normal') % bool(g.group(2))
|
クロージャで名前を(付けた気分に)。
javascript:alert((function($,r){r=[];$.replace(/([a-z]+)(-hidden)?(?:-(big|small))?\.([a-z]+)/gi,function(_,n,h,s,e){r.push(['name:'+n,'ext:'+e,'size:'+(s||'normal'),'hidden:'+!!h].join(', '))});return r.join('\n')})(document.body.innerHTML))
javascript:alert((function($,r){r=[];$.replace(/([a-z]+)(-hidden)?(?:-(big|small))?\.([a-z]+)/gi,function(_,n,h,s,e){r.push(['name:'+n,'ext:'+e,'size:'+(s||'normal'),'hidden:'+!!h].join(', '))});return r.join('\n')})(document.body.innerHTML))
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | function doukaku51($){
var r = [];
$.replace(/([a-z]+)(-hidden)?(?:-(big|small))?\.([a-z]+)/gi, function(_, n, h, s, e){
r[r.length] = { name: n, ext: e, size: s || 'normal', hidden: !!h };
});
return r;
}
(this.WSH ? function($){WSH.echo($)} : alert)((function(a){
for(var i = a.length, k, t; t = [], i--;){
for(k in a[i]) t[t.length] = k +': '+ a[i][k];
a[i] = t.join(', ');
}
return a.join('\n');
})(doukaku51('aaa abc-hidden.png>hoge-big.jpeg\n'+
'---foo-hidden-small.gif|^_^a.bmp\n'+
'--hiddena-hoge.png<=not hidden~~\n'+
'--small.jpg<=not small(^_^)\n'+
'normal-small-big.hoge')));
|
きっともっといい方法あるだろう
1 2 3 4 5 6 7 8 | sub print_image_spec {
$_ = $_[0];
while(my($name, $hidden, $size, $ext, $rest) = /([A-Za-z]+)(-hidden)?(?:-(small|big))?\.([A-Za-z]+)/) {
printf("name:'%s', ext:'%s', size: %s hidden: %s\n",
$name, $ext, $size||'normal', $hidden ? 'True' : 'False');
$_ = $';
}
}
|
1 2 3 4 5 6 7 8 9 | (defun print-image-spec (str)
(ppcre:regex-replace-all "([A-Za-z]+)(-hidden)?(?:-(small|big))?\\.([A-Za-z]+)" str
(lambda (m name hidden size ext)
(format t "name:'~a', ext:'~a', size: ~a hidden: ~a~%"
name ext
(if (zerop (length size)) "normal" size)
(if hidden "True" "False"))
m)
:simple-calls t))
|
カレントバッファを入力としてM-x print-image-spec-on-bufferすると*image-spec*バッファに出力されます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | (require 'cl)
(defun print-image-spec-on-buffer ()
(interactive)
(save-excursion
(goto-char (point-min))
(with-output-to-temp-buffer "*image-spec*"
(while (re-search-forward "\\([A-Za-z]+\\)\\(-hidden\\)?\\(-\\(small\\|big\\)\\)?\\.\\([A-Za-z]+\\)" nil t)
(destructuring-bind (s0 e0 sname ename shidden ehidden _ _ ssize esize sext eext)
(match-data)
(princ (format "name:'%s', ext:'%s', size: %s hidden: %s\n"
(buffer-substring sname ename)
(buffer-substring sext eext)
(if ssize (buffer-substring ssize esize) "normal")
(if shidden "True" "False"))))))))
|
Stringを拡張してます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | class ExtendedString(self:String) {
import java.util.regex._
def regexEach[A](reg:String)(f:(Matcher)=>A) = {
val m = Pattern.compile(reg).matcher(self)
while(m.find) {f(m)}
}
}
implicit def string2ext(self:String) = new ExtendedString(self);
"""
aaa abc-hidden.png>hoge-big.jpeg
---foo-hidden-small.gif|^_^a.bmp
--hiddena-hoge.png<=not hidden~~
--small.jpg<=not small(^_^)
normal-small-big.hoge
""".trim.regexEach("([a-zA-Z]+)(-hidden)?(?:-(small|big))?\\.([a-zA-Z]+)"){ m =>
println("name: '"+m.group(1)+"', ext: '"+m.group(4)+
"', size: "+(if(m.group(3)==null){"normal"}else{m.group(3)}) +
", hidden: "+(if(m.group(2)==null){"False"}else{"True"}))
}
|
良く分かりませんでした。 取り合えずparsecの練習で。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | module Main where
import System
import Char
import Text.ParserCombinators.Parsec hiding (spaces)
import Monad
import Control.Monad.Error
import IO hiding (try)
main = readFile "a.txt" >>= pp >>= print >> return ()
pp s = case parse (many $try(wordx)<|>other) "lisp" s of
(Right x) -> return $filter okparse x
(Left x) -> error "error"
okparse ("",_,_,_) = False
okparse (_,_,_,_)= True
w = many1 letter
hi = do _ <- char '-'
x <- string "hidden"
return x
sz = do _ <- char '-'
x <- try(string "big") <|> string "small"
return x
wordx = do x <- w
(y, z) <- (do yy <-try (hi)
zz <-option "" sz
return (yy,zz))
<|>
(do zz<- option "" sz
return ("", zz))
char '.'
ext <- w
return (x,y,z, ext)
other = do x <- noneOf ""
return ("", "","","")
|
ごめんなさい。プログラミング初心者です。 初めてcl-ppcre使ってみました。 勉強します。精進します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | (defun frob (str)
(let ((l (remove-if-not (lambda (s) (cl-ppcre:scan "\\." s)) (cl-ppcre:split "([^A-z-\\.]|_|\\^)" str))))
(dolist (item l)
(destructuring-bind (name prop _ ext)
(map 'list #'values
(nth-value 1 (cl-ppcre:scan-to-strings "[^A-z]*([A-z]*)((-small|-big|-hidden)*)\\.([A-z]*)" item)))
(declare (ignore _))
(format t "name: '~A',~,8@Text: '~A', ~,8@Tsize: ~[Small~;Normal~;Big~], ~,8@THidden: ~:[False~;True~]~%"
name ext (big-or-small-or-nomal-p prop) (hiddenp prop))))))
(defun hiddenp (str)
(if (cl-ppcre:scan "-hidden[\\.-]*" str) t nil))
(defun big-or-small-or-nomal-p (str)
(cond ((cl-ppcre:scan "-big" str) 2)
((cl-ppcre:scan "-small" str) 0)
('T 1)))
|
その通りですね。訂正しました(今度こそ大丈夫でしょうか)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | import java.util.regex.*;
public class Sample {
private static final Pattern FILE_NAME_PATTERN = Pattern.compile(
"¥¥b(¥¥p{Alpha}+)(-hidden)?(-small|-big)?¥¥.(¥¥p{Alpha}+)¥¥b");
public static void filter(String in) {
Matcher m = FILE_NAME_PATTERN.matcher(in);
while (m.find()) {
String size = "normal";
if ("-big".equals(m.group(3))) {
size = "big";
} else if ("-small".equals(m.group(3))) {
size = "small";
}
System.out.printf("name:'%s', ext:'%s', size: %s, hidden %b%n",
m.group(1), m.group(4), size, "-hidden".equals(m.group(2)));
}
}
public static void main(String[] args) {
filter("aaa abc-hidden.png>hoge-big.jpeg¥n" +
"---foo-hidden-small.gif|^_^a.bmp¥n" +
"--hiddena-hoge.png<=not hidden‾‾¥n" +
"--small.jpg<=not small(^_^)¥n" +
"normal-small-big.hoge¥n");
}
}
|
正規表現使わないと結構面倒ですね。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | #include <iostream>
#include <string>
#include <algorithm>
#include <functional>
#include <iterator>
#include <ctype.h> // isalpha()
struct is_alpha : public std::unary_function<char, bool>
{
bool operator()(char c) const
{
return isalpha(c);
}
};
bool option(
std::string::const_iterator beg,
std::string::const_iterator& it,
const std::string& name,
std::string& ret)
{
const std::string s = "-" + name;
if (std::distance(beg, it) >= s.size() && std::equal(it - s.size(), it, s.begin()))
{
it -= s.size();
ret = name;
return true;
}
else
{
return false;
}
}
void extract(const std::string& s)
{
std::string::const_iterator it = s.begin();
while ((it = std::find(it, s.end(), '.')) != s.end())
{
std::string::const_iterator it2;
it2 = std::find_if(it + 1, s.end(), std::not1(is_alpha()));
const std::string ext(it + 1, it2);
std::string size, hidden;
it2 = it;
option(s.begin(), it2, "big", size) || option(s.begin(), it2, "small", size);
option(s.begin(), it2, "hidden", hidden);
std::string name(
std::find_if(
std::string::const_reverse_iterator(it2),
s.rend(),
std::not1(is_alpha())
).base(), it2
);
if (name.empty())
{
if (!hidden.empty())
{
name.swap(hidden);
}
else if (!size.empty())
{
name.swap(size);
}
}
if (size.empty())
{
size = "normal";
}
std::cout
<< "name:'" << name << "', "
<< "ext:'" << ext << "', "
<< "size: " << size << " "
<< "hidden: " << (!hidden.empty())
<< std::endl;
++it;
}
}
int main()
{
std::boolalpha(std::cout);
extract(
"aaa abc-hidden.png>hoge-big.jpeg\n"
"---foo-hidden-small.gif|^_^a.bmp\n"
"--hiddena-hoge.png<=not hidden~~\n"
"--small.jpg<=not small(^_^)\n"
"normal-small-big.hoge\n"
);
}
|
今までPerl互換の方の正規表現関数は使わなかったのだけれど 繰り返し検索はこっちにしかなかったので使ってみた。 …これからもっと使おう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <?php
$str='aaa abc-hidden.png>hoge-big.jpeg
---foo-hidden-small.gif|^_^a.bmp
--hiddena-hoge.png<=not hidden~~
--small.jpg<=not small(^_^)
normal-small-big.hoge';
$matches=array();
preg_match_all('/([a-zA-Z]+)(-hidden|)(-(small|big)|)\.([a-zA-Z]+)/', $str, $matches, PREG_SET_ORDER );
while(list(,$v)=each($matches))
{ $hd=$v[2]?"True":"False";
$sz=$v[4]?$v[4]:"normal";
echo "name:'${v[1]}', ext:'${v[5]}', size: $sz hidden: $hd\n";
}
?>
|
個人的はProgramming Policyにより、正規表現は封印中 でもParsec は使い方を思い出すのがちょっと面倒ね。 ということで。。。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | import Data.Char
import Text.ParserCombinators.ReadP
type Name = String
type Size = String
type Hidden = Bool
type Info = (Name,Name,Size,Hidden)
pName :: ReadP Name
pName = munch1 isAlpha
pSize :: ReadP Size
pSize = (string "-big" >> return "big")
+++ (string "-small" >> return "small")
+++ (return "normal")
pHidden :: ReadP Hidden
pHidden = (string "-hidden" >> return True)
+++ (return False)
pExt :: ReadP Name
pExt = char '.' >> pName
pInfo :: ReadP Info
pInfo = do { name <- pName
; size <- pSize
; hidden <- pHidden
; ext <- pExt
; return (name,ext,size,hidden)
}
showInfo :: Info -> String
showInfo (name,ext,size,hidden)
= "name:'"++name++"', ext:'"++ext++", size: "++size++" hidden: "++show hidden
readInfo :: ReadS Info
readInfo = readP_to_S pInfo
infoReader :: String -> [Info]
infoReader [] = []
infoReader ccs@(c:cs) = case readInfo ccs of
[] -> infoReader cs
(info,rs):_ -> info : infoReader rs
main :: IO ()
main = test
test :: IO ()
test = putStr $ unlines $ map showInfo $ infoReader $ testdata
testdata = unlines
["aaa abc-hidden.png>hoge-big.jpeg"
,"---foo-hidden-small.gif|^_^a.bmp"
,"--hiddena-hoge.png<=not hidden~~"
,"--small.jpg<=not small(^_^)"
,"normal-small-big.hoge"]
{- 実行例
*Main> :main
name:'abc', ext:'png, size: normal hidden: True
name:'hoge', ext:'jpeg, size: big hidden: False
name:'hidden', ext:'gif, size: small hidden: False
name:'a', ext:'bmp, size: normal hidden: False
name:'hoge', ext:'png, size: normal hidden: False
name:'small', ext:'jpg, size: normal hidden: False
name:'small', ext:'hoge, size: big hidden: False
-}
|
書きわすれましたが、 Text.ParserCombinators.ReadP モジュールを つかっています。Parsecほど細かい情報を扱えませんが、 その分、お気軽に使えます。
Squeak の Smalltalk で。正規表現は使えないので、手続き的に。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | | in delimiters candidates |
in := 'aaa abc-hidden.png>hoge-big.jpeg
---foo-hidden-small.gif|^_^a.bmp
--hiddena-hoge.png<=not hidden~~
--small.jpg<=not small(^_^)
normal-small-big.hoge'.
delimiters := in asSet reject: [:each | each isLetter or: ['-.' includes: each]].
candidates := (in findTokens: delimiters) reject: [:each | each = each sansPeriodSuffix].
World findATranscript: nil.
candidates do: [:cand |
| strm next ext size hidden |
strm := (cand findTokens: '-.') reversed readStream.
ext := strm next.
next := strm next.
(strm peek notNil and: [#(small big) includes: next])
ifTrue: [size := next. next := strm next] ifFalse: [size := 'normal'].
(hidden := strm peek notNil and: [next = #hidden])
ifTrue: [next := strm next].
Transcript cr; show: {#name->next. #ext->ext. #size->size. #hidden->hidden}]
|
それは%の文字列フォーマット操作で全部やってしまおうとせずに 素直にif文を使う方が後々読みやすくていいと思います。
1 2 3 4 5 6 7 8 | ptn = '(?P<name>[a-zA-Z]+)(?P<hidden>-hidden)?(?:-(?P<size>big|small))?\.(?P<ext>[a-zA-Z]+)'
fmt = "name:'%(name)s', ext:'%(ext)s', size: %(size)s, hidden: %(hidden)s"
for g in re.finditer(ptn, dat):
params = g.groupdict()
params["hidden"] = (params["hidden"] == "-hidden")
if not params["size"]: params["size"] = "normal"
print fmt % params
|
Perl 5.10(開発版はPerl 5.9.5)から、named capture が使えるようになります。
see: perl v5.9.5 更新情報
1 2 3 4 5 6 7 8 9 10 11 | sub print_image_spec {
my $str = shift;
while ( $str =~ /(?<name>[A-Za-z]+)(?<hidden>-hidden)?(?:-(?<size>small|big))?\.(?<ext>[A-Za-z]+)/g ) {
printf(
"name:'%s', ext:'%s', size: %s hidden: %s\n",
$+{name}, $+{ext},
$+{size} || 'normal',
$+{hidden} ? 'True' : 'False'
);
}
}
|
とりあえず動くコードをup。 最近のgawkだともっと効率の良い書き方ができるような気がします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | {
s = $0
while (match(s,/[a-z]+(-hidden)?(-small|-big)?\.[a-z]+/)) {
matched = substr(s,RSTART,RLENGTH)
s = substr(s,RSTART+RLENGTH+1)
hyphen = index(matched,"-")
period = index(matched,".")
if (hyphen > 0) {
name = substr(matched, 1, hyphen-1)
extra = substr(matched, hyphen, period - hyphen)
hidden = (extra ~ /-hidden/) ? "True" : "False"
if (extra ~ /-small/) size = "small"
else if (extra ~ /-big/) size = "big"
else size = "normal"
ext = substr(matched, period+1)
} else {
name = substr(matched, 1, period-1)
hidden = "False"
size = "normal"
ext = substr(matched, period+1)
}
printf("name:'%s', ext:'%s', size: %s hidden: %s\n", name, ext, size, hidden)
}
}
|
文字列からパターンにマッチする表現のデータをとりだしたり, 特定のパターンにマッチする表現を別の表現で置換したり, というのが正規表現の使いどころなんだね. (という自明なことに今さら気づきました.^^;) とするとパターンを指定するのは正規表現ではなくて,たとえばもうすこし 拡張してパーザで指定してもいいわけですよね.(これも自明か^^;) たとえば,ReadP a が一般化されたパターンを表すと思えばいいわけでよね... そうすると性能の問題はあるにせよ、 一般化したパターンをもらって,(雑音のある)文字列からデータを取り出す関数を 生成する関数 reader とか,パターン(とデータを文字列に変換する関数)をもらって 文字列のなかの部分列を置換する関数を生成する関数 replacer とかがあれば汎用性 があるはずですよねぇ.(正規表現はまさにこのように使うのでしょうから) そうすると先に投稿したコードでは infoReader の定義は infoReader = reader pInfo となるし,たとえば入力文字列からデータ部分をとりのぞいて雑音部分だけに してしまうにような infoNoise は infoNoise = replacer pInfo (const "") なんてことができますね. *Main> let infoNoise = replacer pInfo (const "") *Main> infoNoise testdata "aaa >\n---foo-|^_^\n--hiddena-<=not hidden~~\n--<=not small(^_^)\nnormal-\n"
1 2 3 4 5 6 7 8 9 10 11 12 13 | reader :: ReadP a -> (String -> [a])
reader parser string = case string of
"" -> []
_ -> case readP_to_S parser string of
[] -> reader parser (tail string)
(a,string'):_ -> a : reader parser string'
replacer :: ReadP a -> (a -> String) -> String -> String
replacer p s str = case str of
"" -> ""
_ -> case readP_to_S p str of
[] -> head str : replacer p s (tail str)
(a,str'):_ -> s a ++ replacer p s str'
|
とりあえずサンプルはできた感じです。多分。 *Main> :!cat sample.txt aaa abc-hidden.png>hoge-big.jpeg ---foo-hidden-small.gif|^_^a.bmp --hiddena-hoge.png<=not hidden~~ --small.jpg<=not small(^_^) normal-small-big.hoge *Main> *Main> :main sample.txt name:'abc', ext:'png', size: normal hidden: True name:'hoge', ext:'jpeg', size: big hidden: False name:'foo', ext:'gif', size: small hidden: True name:'a', ext:'bmp', size: normal hidden: False name:'hoge', ext:'png', size: normal hidden: False name:'small', ext:'jpg', size: normal hidden: False name:'small', ext:'hoge', size: big hidden: False
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | import System (getArgs)
import Control.Monad (liftM)
import Text.ParserCombinators.Parsec
data Val = V {name :: String, ext :: String, hidden :: String, size :: String} | None deriving Eq
instance Show Val where
show (V n e h s) = "name:'" ++ n ++ "', ext:'" ++ e ++ "', size: " ++ s ++ " hidden: " ++ h
show None = ""
alpha = ['a'..'z'] ++ ['A'..'Z']
nameParser :: GenParser Char () String
nameParser = many1 (oneOf alpha)
extParser :: GenParser Char () String
extParser = char '.' >> many1 (oneOf alpha)
hiddenParser :: GenParser Char () String
hiddenParser = try ((string "-hidden") >> return "True") <|> return "False"
sizeParser :: GenParser Char () String
sizeParser = try (string "-small" >> return "small")
<|> try (string "-big" >> return "big")
<|> return "normal"
expression :: GenParser Char () Val
expression = do
n <- nameParser
h <- hiddenParser
s <- sizeParser
e <- extParser
return $ V n e h s
skip :: GenParser Char () Val
skip = manyTill (many1 (oneOf alpha)) (many1 (noneOf alpha)) >> return None
expressionParser :: GenParser Char () [Val]
expressionParser |




にしお
#3407()
Rating0/0=0.00
サンプル入力
サンプル出力
探すべき文字列は下の条件を満たします
出力は以下の条件を満たす必要があります
このお題は、正規表現のグループに名前をつけて連想配列として取得できるPythonからの挑戦状です。
[ reply ]