我正在尝试在Rust中编写一个小程序来完成基本的ssh -L 5000:localhost:8080工作:localhost:5000在我的机器和localhost:8080远程机器之间建立隧道,这样如果HTTP服务器在远程端口8080上运行,我可以访问它我的本地通道localhost:5000,绕过远程的防火墙,可能会阻止外部访问8080.
我ssh已经意识到已经完成了这个并且可靠,这是一个学习项目,如果我让它工作,我可能会添加一些功能:)这是一个准系统(没有线程,没有错误处理)版本的我已经出现到目前为止(应该在Rust 1.8上编译):
extern crate ssh2; // see http://alexcrichton.com/ssh2-rs/
use std::io::Read;
use std::io::Write;
use std::str;
use std::net;
fn main() {
// establish SSH session with remote host
println!("Connecting to host...");
// substitute appropriate value for IPv4
let tcp = net::TcpStream::connect("<IPv4>:22").unwrap();
let mut session = ssh2::Session::new().unwrap();
session.handshake(&tcp).unwrap();
// substitute appropriate values for username and password
// session.userauth_password("<username>", "<password>").unwrap();
assert!(session.authenticated());
println!("SSH session authenticated.");
// start listening for TCP connections
let …Run Code Online (Sandbox Code Playgroud) 每当我考虑学习一种新语言 - 在这种情况下为haskell - 我试图将一个原始的grep克隆组合在一起,看看语言实现和/或它的库在文本处理方面有多好,因为这对我来说是一个主要的用例.
受到haskell wiki代码的启发,我想出了以下天真的尝试:
{-# LANGUAGE FlexibleContexts, ExistentialQuantification #-}
import Text.Regex.PCRE
import System.Environment
io :: ([String] -> [String]) -> IO ()
io f = interact (unlines . f . lines)
regexBool :: forall r l .
(RegexMaker Regex CompOption ExecOption r,
RegexLike Regex l) =>
r -> l -> Bool
regexBool r l = l =~ r :: Bool
grep :: forall r l .
(RegexMaker Regex CompOption ExecOption r, RegexLike Regex l) =>
r …Run Code Online (Sandbox Code Playgroud) 是否有一种惯用的方法,使用Python Click库创建一个命令,其中一个选项取决于前一个选项设置的值?
一个具体的例子(我的用例)是命令将类型选项click.File作为输入,但也是一个编码选项,它指定输入流的编码:
import click
@click.command()
@click.option("--encoding", type=str, default="utf-8")
@click.option("--input",
type=click.File("r", encoding="CAN I SET THIS DYNAMICALLY BASED ON --encoding?"))
def cli(encoding, input):
pass
Run Code Online (Sandbox Code Playgroud)
我想它必须涉及使用可调用的某种延迟评估,但我不确定它是否甚至可以给出当前的Click API.
我发现我可以按照以下几点做一些事情:
import click
@click.command()
@click.pass_context
@click.option("--encoding", type=str, default="utf-8")
@click.option("--input", type=str, default="-")
def cli(ctx, encoding, input):
input = click.File("r", encoding=encoding)(input, ctx=ctx)
Run Code Online (Sandbox Code Playgroud)
但它在某种程度上感觉不太可读/可维护将选项装饰器与适用于它的语义正确类型约束分离,str而是将其作为虚拟放入那里.所以,如果有办法将这两者放在一起,请赐教.
建议的解决方法:
我想我可以使用click.File两次类型,使它在装饰器中变得懒惰,以便文件实际上不会被打开,第一次:
@click.option("--input", type=click.File("r", lazy=True), default="-")
Run Code Online (Sandbox Code Playgroud)
这在语义上更令人满意,但也是多余的.
我有一个 shell 脚本(在 macOS 上运行 GNU bash,版本 3.2.57(1)-release)set -e,但我也想忽略一些潜在的失败,这样它们就不会结束执行的脚本。我通过附加|| ...到相关命令来做到这一点:
#!/bin/sh
set -e
false || echo ignore failure
Run Code Online (Sandbox Code Playgroud)
ignore failure如预期的那样,上述工作和输出。
但是,如果我false通过command内置命令调用该命令,则此策略不起作用 - 脚本的以下版本会在false失败后立即退出,而不打印任何内容:
#!/bin/sh
set -e
command false || echo ignore failure
Run Code Online (Sandbox Code Playgroud)
这是为什么?即使在第二种情况下,我怎样才能获得忽略失败的期望行为?
(在这个简化的示例中,我当然可以删除command内置函数,但在我的实际用例中,它是我无法控制的函数的一部分。)
我正在尝试生成包含小写ASCII字符的向量.这种更复杂的方法有效:
let ascii_lowercase = (b'a'..=b'z').map(|b| b as char).collect::<Vec<char>>();
Run Code Online (Sandbox Code Playgroud)
但是,我首先提出的这个更直接的方法并不是:
let ascii_lowercase = ('a'..='z').collect::<Vec<char>>();
Run Code Online (Sandbox Code Playgroud)
错误是:
error[E0599]: no method named `collect` found for type `std::ops::RangeInclusive<char>` in the current scope
--> src/main.rs:2:39
|
2 | let ascii_lowercase = ('a'..='z').collect::<Vec<char>>();
| ^^^^^^^
|
= note: the method `collect` exists but the following trait bounds were not satisfied:
`std::ops::RangeInclusive<char> : std::iter::Iterator`
`&mut std::ops::RangeInclusive<char> : std::iter::Iterator`
Run Code Online (Sandbox Code Playgroud)
这是奇怪的,因为据我了解,有一个铺盖实现Iterator的RangeInclusive.
是否不可能使用一系列字符作为迭代器?如果是这样,为什么?如果没有,我做错了什么?我正在使用稳定的Rust 2018 1.31.1.
从像Python这样的动态语言来到Rust,我不熟悉编程模式,在这种编程模式中,你提供了一个函数,它具有对空数据结构的可变引用,并且该函数填充它.一个典型的例子是将文件读入String:
let mut f = File::open("file.txt").unwrap();
let mut contents = String::new();
f.read_to_string(&mut contents).unwrap();
Run Code Online (Sandbox Code Playgroud)
对于我熟悉Python的眼睛,你只需在函数中创建一个自有值并将其作为返回值移出的API看起来更直观/符合人体工程学/你有什么:
let mut f = File::open("file.txt").unwrap();
let contents = f.read_to_string().unwrap();
Run Code Online (Sandbox Code Playgroud)
由于Rust标准库采用了以前的道路,我认为必须有一个原因.
是否总是更喜欢使用参考模式?如果是这样,为什么?(性能原因?具体是什么?)如果没有,我如何发现可能有益的情况?除了填充结果数据结构之外,当我想要返回另一个值时,它是否最有用(如上面的第一个示例,其中.read_to_string()返回读取的字节数)?为什么不使用元组?这仅仅是个人偏好的问题吗?