2

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

编写一个以单词和数字作为参数的 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

我该如何解决?

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

4

3 回答 3

3

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

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

说:

IFS=$'\n' read -a filearray <<< `find . -type f -exec grep -l "$word" {} \;`
于 2013-10-17T12:13:24.120 回答
1

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 脚本“查找”输出到数组

于 2013-10-17T12:26:30.283 回答
0

您正在三个不同的时间运行相同的命令!而且,该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

该参数用NUL-print0字符分隔文件名(文件名中不能包含的两个字符之一。为了额外的功劳,您能命名另一个吗?)您将其输入 a以读取文件名。告诉分解空字符上的单词。while read file-d$'\0'read

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

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

((...))一种数学运算。

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


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

于 2013-10-17T12:41:45.167 回答