awkを使用してファイルの末尾の空白行を削除するには?

awkを使用してファイルの末尾の空白行を削除するには?

以下を使用して、ファイルの末尾にある空白行をすべて削除したいと思います。awk

次のコマンドを使用して、上部の空白行をすべて削除する方法を正常に見つけることができました。

awk '/^$/ && a!=1 {a=0} !/^$/ {a=1} a==1 {print}' file.txt

しかし、結論を取り除くために反転する方法がわかりません。上記のコマンドを使用してパイプで接続できることはわかっていますが、可能であればtacコマンドを使用する直接的なアプローチを好みます。awk

明確にすると、「視覚的に空の」行、つまり最大スペースおよび/またはタブを含む行は「空」と見なされます。

答え1

アッ

awkは外部の助け(例えばTac)なしで最初の行から最後の行まで順番にファイルを読み取るので、実際にファイルの終わりに達したときに空の行ブロックがファイルの終わりにあるかどうかだけを知ることができます。

あなたができることは、空行(改行文字、基本レコード区切り文字などRS)を持つ変数を保持し、空でない行に達したら空白行を印刷することです。

awk '/^$/{n=n RS}; /./{printf "%s",n; n=""; print}' file

print nなぜとの間に違いがあるのか​​理解できませんprintf n

print出力レコード区切り記号の追加ORS、デフォルトは改行)を印刷する式に設定します。したがって、試してみると、追加の改行文字が得られます。次のように単一の出力ステートメントを使用して作成することもできます。

awk '/^$/{n=n RS}; /./{printf "%s%s%s",n,$0,RS; n=""}' file

エドまたは前任者

出力を印刷するには(Awkと同様)、次のいずれかのオプションを選択します。

printf '%s\n' 'a' '' '.' '?.?+1,$d' ',p' 'Q'  | ed -s file
printf '%s\n' 'a' '' '.' '?.?+1,$d' '%p' 'q!' | ex -s file

変更をファイルに直接適用するには、次のいずれかのオプションを選択します。

printf '%s\n' 'a' '' '.' '?.?+1,$d' 'w' 'q'   | ed -s file
printf '%s\n' 'a' '' '.' '?.?+1,$d' 'x'       | ex -s file

何が起こっているのか理解してください。

コマンドの置き換え

シェルはコマンド置換から末尾の改行を削除します。

printf '%s\n' "$(cat file)"

一部のシェルは大容量ファイルを処理できず、「引数リストが多すぎる」エラーが発生します。

からインスピレーションを受けるこの回答

答え2

このフェーズ1アプローチは、入力がパイプから出るかファイルから出るかにかかわらず動作しますが、空行の各ブロックはメモリに保存する必要があります(入力に数十億の連続空行がないと実際には機能しない可能性があります)。 )質問)):

awk 'NF{print s $0; s=""; next} {s=s ORS}' file

この2段階のアプローチは、入力がパイプの場合は機能しませんが、入力が質問で言うのと同じファイルであり、メモリをほとんど使用しない場合は機能しません。

awk 'NR==FNR{if (NF) n=NR; next} FNR>n{exit} 1' file file

上記は、空白のみを含む行が「空の」行と見なされると想定しています。これが間違っている場合NFに変更してください/./

答え3

awk 'length == 0 { ++n; next } { for (i = 1; i <= n; ++i) print ""; n = 0 }; 1' file

またはコメントに提案されているように減らしてください。

awk 'length == 0 { ++n; next } { while (n) { print ""; --n } }; 1'

これはカウンターで空の行の実行を追跡しますn

空白行(length == 0)が表示されるたびにカウンタは増加しますが、何も印刷されません。

空でない行が表示される場合は、まず現在行の前に適切な数の空行を出力します。カウンタnもリセットされます。

これにより、ファイルの末尾に空白行が出力されるのを防ぎます。


使用標準sed:

sed -n -e :again -e N -e '/[^\n]/!b again' -e p file

これは、バッファに改行以外の内容があるまでバッファに行を追加する明示的なループを導入します。この時点でバッファが出力される。 read の使用中に入力ファイルが終了すると、Nバッファのデータ(改行のみ)は出力されません。

コメントアウトされたコード(最初は#n使用するのと同じようにデフォルトの出力をオフにします-n):

#n

# Label to branch to later.
:again

# Append next line of input to buffer
# with a delimiting newline.
N

# Branch (jump) to :again if there's
# only newlines in the buffer.
/[^\n]/!b again

# Output buffer.
p

答え4

co=`awk '!/^$/{x=NR}END{print x}' filename`
co=$(($co+1))
j="$co,$"
sed -i "${j}d" filename

テストを経てうまく機能しました

関連情報