以下を使用して、ファイルの末尾にある空白行をすべて削除したいと思います。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
テストを経てうまく機能しました