Bash:在循环遍历字符串数组后,不能用空格读出字符串

[英]Bash: cant' read out strings with spaces after looping through array of strings


I am using a loop to read the contents of an array, which contains all of the directories and files in the directory hierarchy called 'music' (contents are strings from the previous output of 'find' command). The idea is to separate the full directory path of each array element in "directory_contents" into substrings according to genre, artist, and title. Since my music directory is sorted first by genre, then by artist, then by title, I am grabbing each relevant item using awk where the delimiter "/" shows up. For example, if the directory looks like this after using find "./Electronic/Squarepusher/My Red Hot Car.aif", I will separate "Electronic", "Squarepusher", and "My Red Hot Car", then store them each in separate arrays for genre, artist, and title. Later I will sort these data, then pipe the sorted output into another utility to print all the directory contents in a nice looking table (haven't done this yet). For now, I am just trying to view the results of the string separation with echo statements, and for the most part it seems to work. However, I can't seem to extract substrings which contain spaces, which isn't good:

我正在使用循环来读取数组的内容,该数组包含名为“music”的目录层次结构中的所有目录和文件(内容是来自“find”命令的上一个输出的字符串)。我们的想法是根据流派,艺术家和标题将“directory_contents”中每个数组元素的完整目录路径分成子串。由于我的音乐目录首先按流派排序,然后按艺术家排序,然后按标题排序,我使用awk抓取每个相关项目,其中分隔符“/”显示。例如,如果在使用find“./Electronic/Squarepusher/My Red Hot Car.aif”之后目录看起来像这样,我会将“Electronic”,“Squarepusher”和“My Red Hot Car”分开,然后分别存储它们。在流派,艺术家和标题的单独数组中。稍后我将对这些数据进行排序,然后将已排序的输出传输到另一个实用程序中,以便在一个漂亮的表中打印所有目录内容(尚未完成此操作)。现在,我只是试图用echo语句查看字符串分隔的结果,并且在大多数情况下它似乎都有效。但是,我似乎无法提取包含空格的子串,这不好:

-->./Hip-Hop/OutKast/title1.aif<--
Genre:
Hip-Hop
Artist:
OutKast
Title:
title1

-->./Hip-Hop/OutKast/title2.aif<--
Genre:
Hip-Hop
Artist:
OutKast
Title:
title2

-->./Hip-Hop/OutKast/title3.aif<--
Genre:
Hip-Hop
Artist:
OutKast
Title:
title3

-->./Jazz/John<--
Genre:
Jazz
Artist:
John
Title:


-->Coltrane/title1.aif<--
Genre:
title1.aif
Artist:

Title:

As you can see, when the loop reads in the string "John Coltrane", it is treating the space as a delimiter, and treating everything after "John" as a different filename. I tried looking for a solution in the bash manual under the section "Arrays" as well as other posts here, but couldn't find a solution that worked for my specific problem (sorry). If anyone has ideas, they would be greatly appreciated. The problematic code appears below, in the for loop (I didn't post the whole script because it is pretty lengthy, but let me if it is needed):

如您所见,当循环读入字符串“John Coltrane”时,它将空格视为分隔符,并将“John”之后的所有内容视为不同的文件名。我尝试在bray手册中的“Arrays”部分以及其他帖子中查找解决方案,但找不到适合我特定问题的解决方案(抱歉)。如果有人有想法,他们将不胜感激。有问题的代码出现在下面,在for循环中(我没有发布整个脚本,因为它非常冗长,但如果需要的话请让我):

#more before this...

#declare variables                                                                                                      
declare -a genre_list                                                                                                   
declare -a title_list                                                                                                   
declare -a artist_list                                                                                                  
declare -a directory_contents                                                                                           


#populate directory with contents                                                                                       
cd $directory                                                                                                           
directory_contents=$(find .  -mindepth 1 -type f)                                                                       
cd ..                                                                                                                   


for music_file in ${directory_contents[*]}; do                                                                          
    if [[ $DEBUG = "true" ]] ; then                                                                                     
        echo "-->$music_file<--"                                                                                        
    fi                                                                                                                  

    echo "Genre:"                                                                                                       
    echo $music_file | awk -F"/" '{print $2}'                                                              
    echo "Artist:"                                                                                                      
    echo $music_file | awk -F"/" '{print $3}'                                                               
    echo "Title:"                                                                                                       
    echo $music_file | awk -F"/" '{print $4}' | awk -F"." '{print $1}'                                     
    echo ""                                                                                                             
done   

4 个解决方案

#1


2  

Why don't you simply do it in single line:

你为什么不单行做:

cd $directory && \
find .  -mindepth 3 -maxdepth 3 -type f | \ 
awk -F'/' '{split($4,A,".aif"); printf "Genre: %s\nArtist: %s\nTitle: %s\n\n",$2,$3,A[1];}'

Update: (removed the .aif from the Title part)

更新:(从标题部分删除.aif)

#2


1  

If you can, you should use Perl for this task:

如果可以,您应该使用Perl执行此任务:

#! /usr/bin/perl

foreach my $fname (<*/*/*>) {
  next unless -f $fname;
  next unless $fname =~ m"^([^/]+)/([^/]+)/([^/.]+)\.\w+$";
  my ($genre, $artist, $title) = ($1, $2, $3);
  printf("Genre: %s\nArtist: %s\nTitle: %s\n\n", $genre, $artist, $title);
}

It is faster and simpler than the shell, and it is immune against whitespace in file names.

它比shell更快更简单,并且不受文件名中的空格的影响。

#3


1  

MUSICDIR="/some/path"
cd "$MUSICDIR"

find  . -type f -print | (IFS=/;while read dot genre artist title
do
    echo =$genre= =$artist= =$title=
done)

#4


0  

You might try setting the delimiter that bash uses. Perhaps to a newline character?

您可以尝试设置bash使用的分隔符。也许是换行符?

IFS=\n
智能推荐

注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:http://www.silva-art.net/blog/2011/05/24/a27a6ea6a6797cec9956bd4deb59a02c.html



 
© 2014-2019 ITdaan.com 粤ICP备14056181号  

赞助商广告