
次のタスクを実行するコードがあります。
#!/bin/sh
CONTENTS=$(cat "somefile")
RELEVANT_LINES=$(echo "$CONTENTS" | grep -E "SEARCHEXPR")
COUNT=$(echo "$RELEVANT_LINES" | wc -l)
私を迷惑にするのは、このコードが3行目を次に置き換えて、提供された正しい出力と比較して一致するものなしで同じ出力を出力しないことです。
COUNT=$(echo "$CONTENTS" | grep -E "SEARCHEXPR" | wc -l)
最後に、一致するものがない場合、RELEVANT_LINESが空の文字列に設定され、echoは行数が1の空の文字列+ \ n行を出力するという事実を追跡しました。
3行目でprintfとecho -nを試してみましたが、エレガントな解決策が見つからず、COUNT=$(echo "$RELEVANT_LINES" | grep '0' | wc -l)
ソースファイル全体を正規表現で2回フィルタリングする必要がないように(ゼロを含むすべての行)を使用しました。
これは正確ではありませんが、正しい解決策が見つかりません。
私はそれがそれほど強力であると確信していないので、スクリプトを書くことをあきらめず、純粋にきれいに-eq ''
パイプを直接使用することを好みます。wc
grepでフィルタリングした後に0行と1行をきれいに区別できるように、変数からファイルの内容を取得する方法についてのヒントはありますか? :)
答え1
CONTENTS
再使用してファイルを保存することは少し重複しますecho
。
lines=$(cat "somefile" | grep -E "SEARCHEXPR")
より具体的に
lines=$(grep -E "SEARCHEXPR" "somefile")
一致する行数だけが必要な場合は、次を使用します。grep -c
count=$(grep -c -E "SEARCHEXPR" "somefile")
あなたが見ている即時の問題は、改行がecho
常に出力されるという事実によって引き起こされます。コマンドの置き換えから少なくとも1行を取得すると、実際に役立ちます。なぜなら、コマンドの置き換えによるものです。末尾の改行を削除。また、末尾の空行でも動作します。これを試して、次を参照してくださいx=$(echo foo; echo; echo); echo "$x"
。
計算以外の方法でシェルスクリプトの行を処理する場合は、テキストを変数に保存するのが最善の選択ではない可能性があります。あなたは試すことができます
for line in $lines ; do
something with "$line"
done
しかし、これは引用されていない変数、つまりファイル名のグロービングやスペースのトークン化などの一般的な問題のために困難になります。 「foo bar doo」を含む行は、デフォルトではスペースも区切られているため、3行として扱われます。
ループを使用したい場合がありますが、while read
この場合、プロセス置換をサポートするシェルがより良い場合があります。バラよりバッシュFAQ 001そしてfind & while 以降、変数は変更されませんでした。そしてBashでは、パイプが値を設定しなかった後に読み込みます。。