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

Rust正则提取ffmpeg音频设备名:嵌套引号匹配异常问题

Rust环境下提取ffmpeg音频设备名的解决方案

针对ffmpeg -list_devices输出中含嵌套引号的设备名(如""What U Hear" (Sound Blaster Audigy 5/Rx)"),原正则".*?"无法完整匹配的问题,提供两种可靠实现:

一、改进正则表达式匹配

利用ffmpeg用双引号""转义单个引号的规则,编写能识别转义引号的正则,提取后再还原转义内容:

实现代码

use regex::Regex;

fn extract_audio_devices(ffmpeg_output: &str) -> Vec<String> {
    // 匹配被双引号包裹的内容,支持内部的""转义
    let device_re = Regex::new(r#""((?:[^"]|"")*)""#).unwrap();
    
    device_re.captures_iter(ffmpeg_output)
        .filter_map(|cap| {
            let raw_device = cap.get(1)?.as_str();
            // 将转义的""替换为单个"
            Some(raw_device.replace("\"\"", "\""))
        })
        .collect()
}

// 测试示例
fn main() {
    let sample_output = r#"
    [dshow @ 0000021a7f0a4500] DirectShow audio devices
    [dshow @ 0000021a7f0a4500]  ""What U Hear" (Sound Blaster Audigy 5/Rx)"
    [dshow @ 0000021a7f0a4500]  "Microphone (Realtek Audio)"
    "#;
    let devices = extract_audio_devices(sample_output);
    devices.iter().for_each(|d| println!("{}", d));
}

说明

  • 正则"((?:[^"]|"")*)"的核心是(?:[^"]|""):匹配非引号字符,或连续两个引号(转义的单个引号)
  • 提取后通过replace("\"\"", "\"")还原设备名的原始格式

二、状态机解析(更可控)

如果担心正则的边缘情况,可通过手动遍历字符、维护状态的方式解析,逻辑更直观:

实现代码

fn extract_audio_devices_state(ffmpeg_output: &str) -> Vec<String> {
    let mut devices = Vec::new();
    let mut in_device_name = false;
    let mut current_device = String::new();
    let mut chars = ffmpeg_output.chars().peekable();

    while let Some(c) = chars.next() {
        match c {
            '"' if !in_device_name => {
                in_device_name = true;
            }
            '"' if in_device_name => {
                // 检查下一个字符是否也是",是则为转义引号
                if let Some(&next_c) = chars.peek() {
                    if next_c == '"' {
                        current_device.push('"');
                        chars.next(); // 跳过第二个"
                        continue;
                    }
                }
                // 不是转义引号,结束当前设备名
                devices.push(current_device.clone());
                current_device.clear();
                in_device_name = false;
            }
            _ if in_device_name => {
                current_device.push(c);
            }
            _ => {}
        }
    }

    devices
}

// 测试示例
fn main() {
    let sample_output = r#"
    [dshow @ 0000021a7f0a4500] DirectShow audio devices
    [dshow @ 0000021a7f0a4500]  ""What U Hear" (Sound Blaster Audigy 5/Rx)"
    [dshow @ 0000021a7f0a4500]  "Microphone (Realtek Audio)"
    "#;
    let devices = extract_audio_devices_state(sample_output);
    devices.iter().for_each(|d| println!("{}", d));
}

说明

  • 通过in_device_name标记是否处于设备名的引号区间内
  • 遇到单个引号时切换状态,遇到连续两个引号则视为单个引号添加到设备名中

选择建议

  • 若ffmpeg输出格式稳定,正则方案简洁高效
  • 若需要处理更多不可预见的格式异常,状态机方案更灵活可靠

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 12:42:54