MATLAB:只选择与某些输入字符串重合的文件名

时间:2014-11-24 20:47:10

标签: string matlab struct cell

假设我有一个充满文件名的目录,例如:

1242349_blabla.wav
fdp23424_asdf.wav
o2349_0.wav

我有一个输入文本文件,列出了每个换行符上与这些文件名中的数字一致的唯一ID(例如' 23424'对于上面的第二个文件名)。

我想构建一个文件名结构,只包含该目录中与输入文本文件中某些ID一致的文件名:

fid = fopen('input.txt');
input = textscan(fid, '%s', 'Delimiter', '\n');

filenames = dir(fullfile('/somedir/', '*.wav'));

for i = 1:length(filenames)
    for j = 1:length(input)
        if (strfind(input{1}(j), filenames(i).name)) ~= [])
           % create new struct with chosen filenames
        end
    end
end 

然而,我收到了错误"未定义的功能' ne'对于类型' cell'"的输入参数。我尝试了大量的选择无济于事。此外,输入评估为38x1单元格,但其长度为1,因此内部循环只会进行一次...任何想法?

2 个答案:

答案 0 :(得分:1)

我会使用regular expressions来搜索您的单元格数组中ID的出现位置。正则表达式旨在为您搜索特定字符串中的模式。因为你想在一组字符串中搜索特定的数字,我当然会建议你使用它。具体来说,使用regexp功能,您要搜索的模式是您要搜索的ID。

regexp的工作原理是你可以提供字符串的单元格数组,输出将是另一个单元格数组,其中每个元素都是一个数字数组,用于确定特定模式所在的起始索引。重新寻找单元格数组中特定字符串的开头。如果数组为空,这意味着我们没有找到任何与您正在寻找的模式相匹配的模式。如果它不是空的,那么它将包含ID在字符串中所在位置的起始索引。这并不重要 - 您想确定ID是否存在于特定字符串中,因此检查每个数组是否为空将是有用的。

因此,考虑到您通过dir阅读的文件名,我们可以创建一个单独存储文件名的单元格数组,运行regexp,然后过滤掉那些不在的文件名。 ; t包含您想要的ID。像这样:

f = dir(fullfile('/somedir/', '*.wav'));
filenames = {f.name};
ID = 23424;
check = regexp(filenames, num2str(ID));
filtered_ind = cellfun(@isempty, check);
final_files = f(~filtered_ind);

第一行代码从您想要的目录中读取文件。第二行代码从结构的每个name字段中提取名称作为单元格数组。第三行是您要检查的ID。第四行对文件名进行regexp调用,并搜索包含所需数字的文件名。请注意,我们需要将数字转换为字符串,因为模式应该是一个字符串。之后的下一行找到具有您要查找的ID的文件名,最后一行只是找到那些执行具有您的ID的文件。寻找。

然后您可以继续开始处理。具体来说,您可以遍历此单元格数组并继续在此单元格中为每个元素创建结构:

for i = 1:length(final_files)
    s = final_files(i);  %// Get the dir structure for a file that passed the ID check

    %// Create your structure now...
    %// ...
end 

但是,您要检查的ID 系列。我们可以简单地使用上面的代码并对其应用循环。换句话说,您可以执行以下操作:

fid = fopen('input.txt');
input = textscan(fid, '%s', 'Delimiter', '\n');
IDs = input{1};

f = dir(fullfile('/somedir/', '*.wav'));
filenames = {f.name};

for idx = 1 : length(IDs)
    %// Get an ID
    ID = IDs{idx};

    %// Do our checking and filter out those files that don't contain our ID
    check = regexp(filenames,ID);
    filtered_ind = cellfun(@isempty, check);
    final_files = f(~filtered_ind);

    %// Do your final processing
    for i = 1:length(final_files)
        s = final_files(i);  %// Get the dir structure for a file that passed the ID check

        %// Create your structure now...
        %// ...
    end 
end

使用上面的代码,我们打开文本文件,然后解析文本文件中的每个字符串,并将其放入名为IDs的单元格数组中。请注意,ID现在都是字符串,因此无需进行任何转换。之后,对于我们拥有的每个ID,我们会搜索我们的文件名,以查看哪些文件具有我们正在寻找的ID。我们过滤掉那些没有此ID的文件名,然后我们遍历这些文件中的每一个并创建我们的结构。我们为每个ID都这样做。


只是为了证明这些regexp内容正在发挥作用,作为一个小例子,让我们使用您在帖子中提供的三个文件名。我已将这些名称放在单元格数组中,然后我将在我编写的代码中运行第3行到第5行,然后我将过滤掉那些不包含我们的ID的文件名。寻找:

filenames = {'1242349_blabla.wav'; 'fdp23424_asdf.wav'; 'o2349_0.wav'};
ID = 23424;
check = regexp(filenames, num2str(ID));
filtered_ind = cellfun(@isempty, check);
final_filenames = filenames(~filtered_ind);

final_filenames是一个包含我们ID的文件名的单元格数组。我们得到:

final_filenames = 

    'fdp23424_asdf.wav'
祝你好运!

答案 1 :(得分:1)

正则表达式绝对是最灵活,最强大的解决方案。但是,如果您的需求更简单......您可以使用更简单的方法,例如在dir命令中使用通配符。尝试这样的事情:

%get your file IDs from the input file
fid = fopen('input.txt');
input = textscan(fid, '%s', 'Delimiter', '\n');
IDs = input{1};

%loop over each string
myfilenames = {};
for idx = 1:length(IDs)
    %get all files build off the given ID
    fnames = dir(['somedir/*' IDs{idx} '*.wav']);  %wildcards!

    %gather the new filenames that match
    for Ifname=1:length(fnames)
        myfilenames{end+1}=fnames(Ifname).name;
    end
end