複数のファイルを処理するときに行を数える問題

複数のファイルを処理するときに行を数える問題

長くて混乱していたらすみません。cat、、、dogという3つのファイルがありますcow

私のコードは次のとおりです

echo -e "Enter file name: \c"  
read filename                   #saves variable 
if [ -e "$filename" ]
then
total =$(wc -l $filename)       #calculate total lines in the*CAT* file 
echo There are $total         #prints There are *numberoflines*
echo $total > newfile           #writes the answer into a newly created file
else
echo $filename not found
fi

上記のコードを実行すると、次のことが起こります。

  Enter file name : cat
  There are 5 cat 

(プロンプトに入力しcatてファイルの行数を確認しました。)

5行というファイルを実行すると、5 cat出力が表示されます。cat

しかし、同時に3つのファイルをすべて実行したい場合はどうすればよいですか?

次のように表示したいとします。

Enter file name : cat dog cow 
5 cat 
2 dog
14 cow
Total 21

残念ながら

file not found

すべてのファイルを同時に実行しましたが、ファイルごとにスクリプトを1つずつ実行してみると問題はありません。

ベストアンサー1

コメントですでに述べた構文の問題に加えて、コードの主な問題は、複数のファイル名を単一の文字列として読み取った後、その単一の文字列を単一のファイル名として使用することです。

スクリプトのこれらの側面を変更する代わりに、やりたいことをもう一度考えてみましょう。

ユーザーに 1 つ以上のファイル名を指定させ、スクリプトに各ファイルの行数を計算し、各ファイルの行数と総行数を出力させたいとします。また、ユーザーがこの情報を出力ファイルに保存できるようにしたいと思います。ファイル名が存在しない場合は、ユーザーに通知したいと思います。

スクリプトは次のとおりです。

#!/bin/sh -

wc -l -- "$@"

出力を保存せずにテストします。

$ ./script.sh cat dog cow
       5 cat
       2 dog
      14 cow
      21 total

存在しないファイル名でスクリプトを呼び出す:

$ ./script.sh cat dog cow hamster
       5 cat
       2 dog
      14 cow
wc: hamster: No such file or directory
      21 total

出力をファイルに保存します。

$ ./script.sh cat dog cow hamster >output
wc: hamster: No such file or directory
$ cat output
       5 cat
       2 dog
      14 cow
      21 total

スクリプトは、"$@"それぞれ個別に引用されたコマンドライン引数のリストに置き換えられます。つまりcat、を使用してコマンドラインからスクリプトを呼び出すと、dogスクリプト内の項目がリストに展開されます。cow"$@"

このwcユーティリティは、指定されたすべてのファイルの合計を提供するなど、必要なすべての操作をすでに実行しているため、スクリプトのコマンドラインにリストされているファイル名に-lオプションを使用してユーティリティを呼び出して行数を計算する必要があることだけです。

デフォルトでは、出力は標準出力に書き込まれます。これにより、スクリプトユーザーは出力を目的の場所に簡単にリダイレクトできます。

また、インタラクティブなプロンプトで各ファイル名を手動で作成するよりも、タブ補完またはファイル名グロービングパターンを使用してスクリプトにコマンドライン引数を提供する方がはるかに便利です。この場合、スクリプトコードも大幅に簡素化されます。

あなたは何ですか可能さらに確認したいことは、提供されていない場合にユーザーに苦情を申し立てることです。どのファイル名。それ以外の場合、wcユーティリティは標準入力から読み始めるため、少し混乱する可能性があります。

いくつかの方法でこれを行うことができますが、ここではブーストスクリプトの2つのバリエーションを紹介します。

#!/bin/sh -

if [ "$#" -eq 0 ]; then
    echo 'expected to get filename argument(s)' >&2
    exit 1
fi

wc -l -- "$@"

$#スクリプトが取得したコマンドライン引数の数である値を調べます。値が0の場合、ステートメントは診断メッセージを印刷してからスクリプトを終了するifように分岐します。echo

#!/bin/sh -

wc -l -- "${@?expected to get filename argument(s)}"

これは同様の操作を実行しますが、非常に異なるメカニズムを使用します。空であるか設定されていない場合、拡張により${variable?word}診断メッセージがword出力に書き込まれ、"$@"スクリプトも終了します。

これは次のようになります。

$ ./script.sh
./script.sh[3]: @: expected to get filename argument(s)

おすすめ記事