You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Rust中合并Vec中含引号的元素以处理Shell输入

处理Shell输入中的引号拆分问题

当处理类似test "one two" three这样的Shell命令输入时,使用split_whitespace()会把引号包裹的内容拆分成多个元素(比如变成["test", "\"one", "two\"", "three"]),我们需要实现search_quotes函数,将引号内的元素合并为单个元素,最终生成包含正确关键字和参数的Command结构体。

现有代码框架

struct Command {
    keyword: String,
    args: Vec<String>,
}

fn main() {
    let mut c: String = String::from("test \"one two\" three");
    let cmd: Vec<String> = c.split_whitespace().map(|s| s.to_string()).collect();
    
    let command: Command = search_quotes(cmd);
}

fn search_quotes(c: Vec<String>) -> Command {
    // 需将引号包裹的元素合并为一个
    Command {
        keyword: "test".to_string(),
        args: ["\"one two\"".to_string(), "three".to_string()].to_vec()
    }
}

未完成的尝试代码

let cmd = vec!["test", "\"one", "two\"", "three"];
let mut n: Vec<usize> = vec![];
for i in 0..cmd.len() {
    let bytes = cmd[i+1].as_bytes();
    for (j, &item) in bytes.iter().enumerate() {
        if item == b'"' {
            if j == 0 || j == bytes.len()-1 {
                let n = n.push(i+1);
            }
        }
    }
}

正确实现方案

通过遍历拆分后的元素,跟踪引号包裹状态来合并对应内容:

struct Command {
    keyword: String,
    args: Vec<String>,
}

fn main() {
    let c: String = String::from("test \"one two\" three");
    let cmd: Vec<String> = c.split_whitespace().map(|s| s.to_string()).collect();
    
    let command = search_quotes(cmd);
    println!("Keyword: {}", command.keyword);
    println!("Args: {:?}", command.args);
}

fn search_quotes(mut parts: Vec<String>) -> Command {
    let mut merged = Vec::new();
    let mut in_quote = false;
    let mut current_quoted = String::new();

    for part in parts.drain(..) {
        if in_quote {
            // 处于引号中,继续拼接当前部分
            current_quoted.push(' ');
            current_quoted.push_str(&part);
            // 检查是否到达引号结尾
            if part.ends_with('"') {
                let trimmed = current_quoted.trim_matches('"');
                merged.push(trimmed.to_string());
                in_quote = false;
                current_quoted.clear();
            }
        } else {
            if part.starts_with('"') {
                if part.ends_with('"') {
                    // 单个元素就是完整引号内容,直接去引号加入
                    let trimmed = part.trim_matches('"');
                    merged.push(trimmed.to_string());
                } else {
                    // 开启引号包裹状态,保存当前部分
                    in_quote = true;
                    current_quoted.push_str(&part);
                }
            } else {
                // 普通元素直接加入结果
                merged.push(part);
            }
        }
    }

    // 处理未闭合的引号(直接保留原始拼接内容)
    if in_quote {
        merged.push(current_quoted);
    }

    // 提取命令关键字和参数列表
    let keyword = merged.remove(0);
    Command {
        keyword,
        args: merged,
    }
}

实现说明

  • 用in_quote标记是否处于引号包裹状态,遍历所有拆分后的元素
  • 遇到开头引号且未结尾的元素时,开始拼接后续元素,直到遇到结尾引号
  • 拼接完成后去除首尾引号,作为单个参数加入结果列表
  • 最后从合并后的列表中提取第一个元素作为命令关键字,剩余元素作为参数

内容的提问来源于stack exchange,提问作者h1kkar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 01:19:50