2

私はコースプロジェクトに取り組んでいます!宿題のテキストは以下のとおりです。

単語と数字を引数として取るシェル スクリプトを作成します。次に、現在のディレクトリ内のすべてのファイルをチェックし、指定された単語を少なくとも指定された回数含むファイルを見つけます。

サンプル出力は次のようになります。

$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 のように見えるはずです。

無題

Document.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

array への Bash スクリプトの「find」出力に部分的に基づいています。

于 2013-10-17T12:26:30.283 に答える
0

同じコマンドを 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 文字 (ファイル名に含めることができない 2 つの文字のうちの 1 つ。念のため、もう一方の文字に名前を付けることができますか?) でファイル名を区切ります。これを a にパイプしてwhile read file、ファイル名を読み取ります。は、ヌル文字で単語を分割するように-d$'\0'指示します。read

これは、ファイル名のスペースだけでなく、タブ、ダブル スペース、改行、改行、およびミックスに放り込むことができるその他のほとんどすべてを処理します。ファイル名がどんなに風変わりなものであっても、1 つのファイル名しか読み取っていないことが保証されます。

コマンドの出力をwhile readステートメントにパイプすることは、かなり効率的な操作です。それは並行して進むことができます。つまり、コマンドの出力がパイプ処理されている間、whileループが実行されます。このループの構造をよく見てください。これは、シェル スクリプトで何度も目にすることになるからです。

((...))数学演算です。

here be dragons...は、必要な情報を取得するためのロジックを入力する場所です。やっぱり宿題です。ただし、シェル スクリプトをうまく処理しているようです。


これら 2 つの配列が必要な場合は、 の出力を配列にパイプし、findその配列を使用して情報をnumarrayおよびに入れますfilearray。効率的ではありませんが、少なくともfindコマンドを 3 回別々に実行していません。

于 2013-10-17T12:41:45.167 に答える