行末を維持しながらファイルを同時に読み込み、追加します。

行末を維持しながらファイルを同時に読み込み、追加します。

概念的には簡単な作業があります。ファイルに[ゆるい]構造化データがあります。

Testing: debug, default CXXFLAGS
<100's of additional output lines>
Testing: release, default CXXFLAGS
<100's of additional output lines>
...

私はそれをログファイルにまとめようとしています:

echo "Configurations tested:" | tee -a "$TEST_RESULTS"
echo $($GREP 'Testing: ' "$TEST_RESULTS" | $SED 's/Testing: /    * /g') | tee -a "$TEST_RESULTS"

変える:

Configurations tested:
    * debug, default CXXFLAGS
    * release, default CXXFLAGS

私は得る:

Configurations tested:
1 3way.cpp 3way.h CMakeLists.txt CMakeLists.txt.diff Doxyfile Filelist.txt GNUmakefile
GNUmakefile-cross Install.txt License.txt Readme.txt TestData TestVectors adhoc.cpp.proto
adler32.cpp adler32.h aes.h algebra.cpp algebra.h ...

$TEST_RESULTS私はファイルバッファから読み込んでgrep使用するので、ファイルバッファに大きなダメージを与えたと思いますtee

結果をシェル変数に入れようとすると、行末が失われて$GREP 'Testing: ' "$TEST_RESULTS" | $SED 's/Testing: / * /g'大きな接続が発生します。

* debug, default CXXFLAGS    * release, default CXXFLAGS ... <30 additional configs>

行末を維持しながら同時にファイルを読み込んで追加する方法は?


私は次の部分に進展しました:

ESCAPED=$($GREP 'Testing: ' "$TEST_RESULTS" | $AWK -F ": " '{print "  -" $2 "$"}')
echo $ESCAPED | tr $ '\n' | tee -a "$TEST_RESULTS"

しかし、箇条書きでは機能せず、*先行スペースを削除するようです。

Configurations tested:
-debug, default CXXFLAGS
 -release, default CXXFLAGS

sed新しいラインのクロスプラットフォームに交換することは絶対的な痛みなので、私はそれを使用しません。プラットフォームには、BSD、Cygwin、Linux、OS X、および Solaris が含まれます。

答え1

仮定は、$TEST_RESULTSテスト出力を含むファイルの名前です。私が正しく理解したら、同じファイルにテスト構成リストを追加したいと思います。

したがって、一時ファイルを使用してください。これにより、このファイルが元のファイルに追加されます。

tmpfile="$( mktemp )"
{
    echo "Configurations tested:"
    sed -ne 's/^Testing: \(.*\)/  * \1/p' -- "$TEST_RESULTS"
} >"$tmpfile"

cat <"$tmpfile" >>"$TEST_RESULTS"
rm -f -- "$tmpfile"

それがなければmktemp使用できます

tmpfile="$TEST_RESULTS.tmp"

または

tmpfile=~/tmp/"$(basename -- "$TEST_RESULTS").tmp"

またはこれと似ています...ファイルがまだ存在しないとします(この場合、そのファイル(またはシンボリックリンクで指すファイル)は上書きされ、削除されます)。とにかく、固定名で一時ファイルを作成するためにグローバルに書き込み可能なディレクトリを使用しないでください。これはセキュリティの観点から悪い習慣です。


利用可能なシステムsponge:

{
    echo "Configurations tested:"
    sed -ne 's/^Testing: \(.*\)/  * \1/p' -- "$TEST_RESULTS"
} | sponge -a -- "$TEST_RESULTS"

ここでは、sponge -a前の複合コマンド()の出力が{ ...; }指定された出力ファイルに追加されます。ユーティリティspongeは出力を一時的な場所に書き込み、指定されたファイルをその場所に置き換えます。このオプションは、-a出力を上書きせずに元のファイルに追加します。

答え2

主な問題は、quoteを忘れたため、分割+glob演算子を呼び出すこと$(echo...)です$ESCAPED。ここで、拡張はの文字に基づいて分割され、結果の$IFS単語はワイルドカードの適用を受けます(*例:現在隠されていないファイル名のリストへの拡張)。ディレクトリ)、これは大きな問題です。ほとんどのBourne様シェルに見られる一般的なエラー特性です。

# get a $PATH where to find standard utilities rather having to hardcode
# the path of each (you also forgot the quotes around those `$SED`/`$GREP`...)
PATH=$(command -p getconf PATH)${PATH:+:$PATH}
export PATH

printf '%s\n' 'Configurations tested:' \
              "$(sed -ne 's/^Testing: \(.*\)/  * \1/p' -- "$TEST_RESULTS")" |
  tee -a -- "$TEST_RESULTS"

(また、これを使用して任意のデータを出力できないことに注意してくださいecho。)

答え3

私は次のことを試してみます:

awk -v pattern="Testing:" '$0 ~ pattern { sub(pattern, "  *"); print }' 

sedこれには明確な拡張機能が含まれていないため、すべてのバージョンで機能します。変数を正しく引用する限り、単語の区切りを防ぐために明示的に改行を処理する必要はありません。

関連情報