【问题标题】:Shell script issue with filenames containing spaces while reading into an array读入数组时文件名包含空格的 Shell 脚本问题
【发布时间】:2013-10-17 20:41:45
【问题描述】:

我正在做一个课程项目!作业文本如下:

编写一个以单词和数字为参数的 shell 脚本。 然后它检查当前目录中的所有文件,并找出哪些文件 至少包含给定的单词给定的次数。

样本输出应该是:

$myprog3.sh write 2
The file "./file-comp.sh" contains the word "write" 3 times.
The file "./homework.log" contains the word "write" 11 times.

我写了一些代码,但是在将文件名读入数组时遇到了问题。

count=`find . -type f -exec grep -H $word {} \; | wc -l`
read -a filearray <<< `find . -type f -exec grep -l "$word" {} \;`
read -a numarray <<< `find . -type f -exec grep -c "$word" {} \;`
size=${#filearray[@]}
echo "Array size is "$size""
for x in `seq 0 $size`
do
echo $x
echo "${filearray[x]}"
done

输出看起来像这样:

Array size is 5
0
./UntitledDocument.tex~
1
./Untitled
2
Document.tex
3
./wordcounter.sh
4
./wordcounter.sh~
5

例如:它应该看起来像 Untitled Document.tex 而不是

无标题

文档.tex

我该如何解决?

对于完整的问题,您能否为我提供一个解决方案? 提前谢谢..

【问题讨论】:

  • 你的意思是 :size=${#filearray[@]} echo "Array size is "$size"" for x in "${filearray[@]}";do echo "$x " 完成 但还是一样 :(

标签: bash shell


【解决方案1】:

文件名中的空格导致它在分配给数组时被拆分。最简单的方法是将IFS 定义为不包含空格的东西。而不是说

read -a filearray <<< `find . -type f -exec grep -l "$word" {} \;`

说:

IFS=$'\n' read -a filearray <<< `find . -type f -exec grep -l "$word" {} \;`

【讨论】:

  • 在 4 个多月的帖子发布后吸引反对票有什么问题?有人可以留下便条,而不是指出问题所在吗?
【解决方案2】:

grep -Hc 将输出

file:number_of_ocurrencies

你可以这样做:

declare -A arr
while IFS=: read file count
do
    arr["$file"]=$count         #### "$file" to allow spaces on the names
done < <(find . -type f -exec grep -Hc "$word" {} \;)

这样你就有了一个关联数组

([file1]=>number_of_ocurrencies_file1 [file2]=>number_of_ocurrencies_file2)

然后你可以循环如下:

for key in "${!arr[@]}"; do    ### double quotes to accept keys with spaces
    echo "$key = ${arr[$key]}"
done

部分基于Bash script “find” output to array

【讨论】:

    【解决方案3】:

    您在三个不同的时间运行相同的命令!而且,find 命令可能需要很长时间才能运行。

    我会看看你的循环,看看你是否可以在单个循环中完成所有步骤:

    file_count=0
    find . -type f -print0 | while read -d $'\0' file
    do
        ((file_count+=1))  #Count the number of files processed
        here be dragons...
        echo "The '$file' file contains '$word' $word_count times"
    done
    

    -print0 参数用NUL 字符(不能包含在文件名中的两个字符之一。为了额外的信用,你能命名另一个吗?)你管道这个进入while read file 以读取文件名。 -d$'\0' 告诉read 分解空字符上的单词。

    这不仅可以处理文件名中的空格,还可以处理制表符、双空格、回车符、换行符以及几乎任何其他可以混入其中的内容。无论文件名多么时髦,您都可以确保您正在读取一个且只有一个文件名。

    将命令的输出通过管道传输到while read 语句中是一种相当有效的操作。它可以并行。也就是说,当命令的输出通过管道传输时,while 循环正在执行。好好看看这个循环的结构,因为你会在你的 shell 脚本中一遍又一遍地看到它。

    ((...)) 是一个数学运算。

    这里是龙......是您填写逻辑以获取所需信息的地方。毕竟,这是一项家庭作业。但是,您似乎对 shell 脚本有很好的掌握。


    如果您必须拥有这两个数组,我会将find 的输出通过管道传输到一个数组中,然后使用该数组将您的信息放入numarrayfilearray。它效率不高,但至少您没有分别运行三次find 命令。

    【讨论】:

      猜你喜欢
      • 2013-03-08
      • 2012-10-21
      • 2013-02-22
      • 1970-01-01
      • 2013-03-25
      • 2011-02-02
      • 2013-05-23
      • 1970-01-01
      • 2019-03-18
      相关资源
      最近更新 更多