Bash 組み込みの「読み取り」がコメントや空白行を無視するようにするにはどうすればよいですか?

Bash 組み込みの「読み取り」がコメントや空白行を無視するようにするにはどうすればよいですか?

(単純化のために読み取るファイルが最初の引数であると仮定します。$1

私は私が望むことをすることができます外部的にそして:

tempfile=$(mktemp)
awk '/^#/ {next}; NF == 0 {next}; {print}' "$1" > $tempfile
while read var1 var2 var3 var4 < $tempfile; do
  # stuff with var1, etc.
done

awkしかし、設定ファイルを解析するたびにそれを呼び出さなければならないということはとんでもないようです。readファイルのコメント行または空白行を無視する方法はありますか?いいえ外部バイナリ/潜在的なパフォーマンスの問題はありますか?


これまでの答えはとても役に立ちます!はっきり言えば一時ファイルを使いたくないけどする構成を読みたいです。ファイルから、標準入力ではありません。スクリプトを呼び出すときに入力リダイレクトを使用できることはよくわかっていますが、いくつかの理由で私の場合、これはうまくいきません。

読みたい入力をソフトエンコードしたいです。たとえば、次のようになります。

configfile="/opt/myconfigfile.txt"
[ $# -gt 0 ] && [ -r "$1" ] && configfile="$1"

while read var1 var2 var3 var4 < "$configfile" ; do
  ...

configfileただし、これを試みると、プロセスが終了するまで最初の行を読み続けます。

たぶんこれはそれ自体の質問でなければならないかもしれませんが…私がやっていることから行が変わるかもしれません。私の間違いはどこにありますか?

ベストアンサー1

これを行うために一時ファイルは必要なく、sed(またはawk)はシェルケースステートメントよりもコメントアウトにはるかに柔軟です。

たとえば、

configfile='/opt/myconfigfile.txt'
[ $# -gt 0 ] && [ -r "$1" ] && configfile="$1"

sed -e 's/[[:space:]]*#.*// ; /^[[:space:]]*$/d' "$configfile" |
    while read var1 var2 var3 var4; do
      # stuff with var1, etc.
    done

# Note: var1 etc are not available to the script at this
# point. They are only available in the sub-shell running
# the while loop, and go away when that sub-shell ends.

これにより、コメント(先行スペースを含めるか除く)が削除され、whileループに入力を供給する前に入力から空白行が削除されます。その行のコメントと行の末尾に追加されたコメントを別々に処理します。

# full-line comment
# var1 var2 var3 var4
abc 123 xyz def # comment here

このような電話やsed仕事はawk「愚かな」仕事ではなく、完全に正常なものです。これがこのツールの目的です。パフォーマンスに関しては、非常に小さな入力ファイルを除いて、このバージョンははるかに高速になると確信sedしています。配管にはsed少しの開始オーバーヘッドがありますが、非常に高速に実行されますが、シェルは遅いです。


2022年5月3日に更新:

while ループ (var1、var2、var3 など) に設定された変数は、while ループが終了すると「範囲外」です。 whileループ内でのみ使用できます。 whileループは、構成ファイルがパイプでリンクされているため、サブシェルで実行されます。サブシェルが死ぬと、その環境とサブプロセスも一緒に消えます。できない親プロセスの環境を変更します。

whileループ後も変数の値が保持されるようにするには、パイプの使用を避ける必要があります。たとえば、入力リダイレクト(<)を使用します。プロセスの交換( <(...)):

while read var1 var2 var3 var4; do
  # stuff with var1, etc.
done < <(sed -e 's/[[:space:]]*#.*// ; /^[[:space:]]*$/d' "$configfile")

# remainder of script can use var1 etc if and as needed.

このプロセス代替バージョンでは、whileループは親シェルで実行され、スクリプトsedは子プロセスとして実行されます(その出力はwhileループにリダイレクトされます)。 sedとその環境は完了すると消えますが、whileループを実行するシェルはループによって生成/変更された変数を保持します。

おすすめ記事