私はシェルスクリプトを作成しましたが、スクリプトに引数として渡された各ファイルの行数を印刷するループを実行する方法がわかりません。出力は次のとおりです。
2 lines in hello.sh
33 lines in /var/log/syslog
答え1
POSIXシェルを想定すると、ここでコマンドライン引数を含むfor
ループを使用してループを実行する必要があります。"$@"
for filename in "$@"; do
lines=$(wc -l < "$filename")
printf '%u lines in %s\n' "$lines" "$filename"
done
すべての引用符を使用することは非常に重要です。スペースやその他の文字を含むファイル名を渡すことができます。
./my_script.sh /var/log/syslog "$HOME/My Dir with Spaces/a file with spaces.txt"
答え2
通常、スクリプトまたはシェル関数でコマンドライン引数を繰り返すには、次の手順を実行します。
for thing do
commands using "$thing"
done
または
for thing in "$@"; do
commands using "$thing"
done
この場合、コマンドラインで指定されたファイル名にリテラル改行が含まれていないと仮定すると、これに対して明示的なシェルループを実行する必要はありません。
wc -l -- "$@" | sed -E '$d;s/^[[:blank:]]*([[:digit:]]*)[[:blank:]]*(.*)/\1 lines in \2/'
これにより、すべてのコマンドライン引数が使用され、wc -l
すべて実行されます。
出力を解析して、指定されたsed
ファイルの総行数を含む最後の行を削除します(使用$d
)。wc -l
行番号とファイル名をキャプチャし、その間に文字列を挿入して残りの出力lines in
を目的の出力に変換します。
私自身のスクリプト.vimrc
を実行すると、.profile
ファイル.mailrc
が返されます。
8 lines in .vimrc
8 lines in .profile
4 lines in .mailrc
これにより、次wc -l -- "$@"
のような出力が生成されます。
8 .vimrc
8 .profile
4 .mailrc
20 total
これは実際に必要なく、あなたのニーズに十分かもしれませんsed
。
答え3
#!/bin/bash
for file in "${@}"; do
wc -l -- "${file}"
done
#!/bin/bash
スクリプトを実行するプログラムです。
${@}
位置引数。コマンドラインを介してスクリプトに提供する引数。
file
引数で指定された変数を繰り返します${@}
。
wc -l -- "${file}"
行数を印刷する外部コマンド(標準入力の行数を印刷する場合${file}
を除く)${file}
-
答え4
代替用途while
とshift
while [ $# -gt 0 ] ; do
printf '%u lines in %s\n' $(wc -l < "$1") "$1"
shift
done