2015-08-29 40 views
3

我在玩Turtle,我遇到了以下问题。如何grep海龟的ls结果

我想这样做(带壳)

ls | grep 'foo' 

使用龟我的尝试是

grep (prefix "foo") (ls ".") & view 

,但我得到了以下信息

Couldn't match type ‘Turtle.FilePath’ with ‘Text’ 
Expected type: Shell Text 
    Actual type: Shell Turtle.FilePath 
In the second argument of ‘grep’, namely ‘(ls ".")’ 
In the first argument of ‘(&)’, namely 
    ‘grep (prefix "foo") (ls ".")’ 

我明白ls回报FilePathgrep适用于Text,那我该怎么办?

更新

有明显这涉及到来回转换,从FilePathText解决方案。这超出了我期望的类似shell的程序的简单性。

有人提到了find函数,它可以以某种方式解决问题。 但是find相当于find shell函数,我只是想做ls | grep "foo"。我并没有试图解决现实生活中的问题(如果是的话,我会转而使用bash),但是试图结合简单的砖块,就像我在bash中做的那样。不幸的是,它似乎并没有在龟砖是易:-(结合起来。

回答

0

尝试使用repr

repr :: Show a => a -> Text 
+0

+1不坏,但能够解决一半的问题。假设我想将选定的文件移动到某处,然后我需要将它们转换回'FilePath'。 – mb14

+1

'repr'在ghci中有效,但我无法在您提供的链接上找到它。 – mb14

+0

@ mb14我编辑了答案以包含正确的链接。还要注意''repr = format w''格式描述[这里](https://hackage.haskell.org/package/turtle-1.0.0/docs/Turtle-Format.html#v:format)。 – Bakuriu

1

相反的grep,我们可以使用match,结合了MonadPlus实例的Shell过滤:

filterByPattern :: MonadPlus m => Pattern x -> FilePath -> m FilePath 
filterByPattern somepattern somepath = 
    case match somepattern (either id id (toText somepath)) of 
     []  -> mzero 
     otherwise -> return somepath 

greppedls :: FilePath -> Pattern x -> Shell FilePath 
greppedls somepath somepattern = 
    ls somepath >>= filterByPattern somepattern 

编辑:而不是使用unnecesarily一般MonadPlus的,这里的该过滤器使用特定乌龟组合子select的实现:

filterByPattern :: Pattern x -> FilePath -> Shell FilePath 
filterByPattern somepattern somepath = 
    case match somepattern (either id id (toText somepath)) of 
     []  -> select []   -- no matches, so filter this path 
     otherwise -> select [somepath] -- let this path pass 

foo :: Shell a是有点像“的a的名单”。如果我们有一个函数genlist :: a -> Shell b,那么对于每个a生成一个(可能是空的!)列表b s,我们可以使用(>>=)运算符获得b s的列表:foo >>= genlist

编辑#2:标准海龟功能find已经使用模式过滤文件。它是递归的,并在子目录中进行搜索。

+0

您的代码可能会编译但不起作用。 'repr(Filepath“foo”)'不返回''foo“'但是'Filepath \”foo \“'这意味着'prefix”foo“'不会匹配'foo'文件。这是一个更好的bash,这个代码比bash等效的'ls | grep“foo”'太复杂了。 – mb14

+0

@ mb14我已经通过使用['toText']去除了'repr'问题(http:/ /hackage.haskell.org/package/system-filepath-0.4.13.4/docs/Filesystem-Path-CurrentOS.html#v:toText) – danidiaz

+0

@ mb14至于过度复杂,或许像'filterByPattern'这样的东西应该在(或者它已经存在了,我没有看到它),一旦存在这样的函数,'ls“。”>> = filterByPattern“foo”'不比'ls | grep'foo“'糟糕! 。 – danidiaz

1

从文件路径转换为文本使用:

fp :: Format r (FilePath -> r) 

下面是一个例子:

format fp ("usr" </> "lib") 

有几个关于这个所以加布里埃尔已决定更新教程的几个问题天前:

https://github.com/Gabriel439/Haskell-Turtle-Library/commit/a2fff2acf912cc7adb2e02671340822feb0e9172

要回答你的(更新)的问题,我可以拿出最好的是:

format fp <$> ls "." & grep (has "foo") & view 

&正在播放的|的作用。

作为个人笔记,它当然不像ls | grep 'foo'那么短,但鉴于Haskell是一种类型语言,它仍然非常优雅。

1

字面上的答案是这样的一行代码:

example = 
    view (ls "." & fmap (format fp) & grep (prefix "foo") & fmap toText) 

惯用的答案是使用find实用