2015-08-29 104 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實用