如何将`Shell Text`转换为`Shell Line`?及Turtle脚本ssh-add调用问题咨询
Alright, let's break down your two questions with practical, Turtle-specific solutions—no jargon overload, just straight-to-the-point fixes.
Shell Text to Shell Line in Turtle First off, let's clarify the difference: in Turtle, Shell Text is a stream of raw text chunks (think unbroken blobs of text), while Shell Line is a stream of text split neatly by newlines. To convert between them, Turtle gives you a ready-made function that does all the line-splitting heavy lifting: textLines.
Here's how to use it in practice:
import Turtle -- Example: A Shell Text stream from a file rawTextStream :: Shell Text rawTextStream = input "my-keyring-output.txt" -- Convert it to a Shell Line stream (split by newlines) lineStream :: Shell Line lineStream = textLines rawTextStream
If you ever need to go the other way (turn Shell Line back into Shell Text), just map lineToText over the stream to unwrap the Line wrapper:
backToRawText :: Shell Text backToRawText = fmap lineToText lineStream
Let's start by fixing the core logic of your function. I'll walk through common pitfalls people hit with this use case, then share a working example you can adapt to your keyring's format.
First, here's a revised version of the function with explanations for each step:
import Turtle import qualified Data.Text as T -- Type alias to make the function signature cleaner type SshKeyParams = (FilePath, Text) addSshKeyFromKeyring :: SshKeyParams -> Shell Line -> IO () addSshKeyFromKeyring (keyFilePath, searchString) keyRingLines = do -- Step 1: Filter lines in the keyring that contain our target search string let matchingEntries = filter (T.isInfixOf searchString . lineToText) keyRingLines -- Step 2: Extract the password from the matching line (ADJUST THIS TO YOUR KEYRING FORMAT!) -- Example: If keyring lines look like "ssh-key-name:my-password", split on ":" let passwords = fmap extractPassword matchingEntries -- Step 3: Call ssh-add, passing the password via stdin (ssh-add reads passwords from standard input) sh $ passwords >>= \pwd -> proc "ssh-add" [keyFilePath] (pure $ pwd <> "\n") where extractPassword :: Line -> Text extractPassword line = case T.splitOn ":" (lineToText line) of [_, password] -> T.strip password -- Strip extra whitespace just in case _ -> error $ "Invalid keyring entry format: " ++ T.unpack (lineToText line)
Common Mistakes We're Fixing:
- Forgetting to unwrap
Line:Lineis a wrapper type in Turtle, so you can't run text operations on it directly. We uselineToTextto convert it to aData.Textvalue before searching or parsing. - Incorrect password parsing: Your keyring's entry format will vary—maybe it uses a different delimiter, or stores the password in a specific position. The
extractPasswordfunction above is an example; tweak it to match how your keyring saves SSH key passwords. - Not passing the password correctly to ssh-add:
ssh-addexpects the password to come from standard input (command-line arguments are insecure!). Usingprocwith the third argument lets us pipe the password directly into ssh-add's stdin. - Handling multiple matches: If your search string might pull up multiple entries, the function above will try to add the key with each password. If you only expect one match, use Turtle's
singlefunction to enforce that (it'll throw a clear error if there's zero or multiple matches):
-- Version for single expected match addSshKeySingleMatch :: SshKeyParams -> Shell Line -> IO () addSshKeySingleMatch (keyFilePath, searchString) keyRingLines = do matchingEntry <- single $ filter (T.isInfixOf searchString . lineToText) keyRingLines let password = extractPassword matchingEntry sh $ proc "ssh-add" [keyFilePath] (pure $ password <> "\n")
Quick Testing Tips:
- Before running ssh-add, test the filtering step by printing matching lines:
sh $ matchingEntries >>= echo - Verify the password extraction works by printing the parsed password:
sh $ passwords >>= echo - If ssh-add complains about the password, check for extra whitespace—adding
T.stripto the password extraction helps catch that.
内容的提问来源于stack exchange,提问作者user4301448

