質問
いすべて削除し、空のラインからのファイルがその時にファイルにはがない場合には、空行の前に買い替えることができるようにし、開始;とがない場合は空行後の買い替えることができるようにします。)
こんなことが可能なので外のエスクリプト言語のようなPerlやルビー?いうこと sed
または awk
が可能です。基本的には、軽量で、幅広くご利用UNIX-yいツールは、特について深く学ぶことができます迅速に(Perlが含まれません。)
解決
# Delete all leading blank lines at top of file (only).
sed '/./,$!d' file
# Delete all trailing blank lines at end of file (only).
sed -e :a -e '/^\n*$/{$d;N;};/\n$/ba' file
したがって、ファイルから先頭の空白線と後続の両方の行を削除するには、上記のコマンドを以下に結合できます。
sed -e :a -e '/./,$!d;/^\n*$/{$d;N;};/\n$/ba' file
他のヒント
だから私はこれに対する @dogbaneの答えの一部を借りるつもりです。 sed
主要な空白線を取り外すためのラインはとても短いです...
tac
Coreutilsの一部です, 、およびファイルを逆にします。だから二度それをする:
tac file | sed -e '/./,$!d' | tac | sed -e '/./,$!d'
それは確かに最も効率的ではありませんが、あなたがいない限り 必要 効率性、私はそれがこれまで他のすべてよりも読みやすいと思います。
これはAWKのワンパスソリューションです。空のラインが表示されるまで印刷を開始しません。
awk '
/[[:graph:]]/ {
# a non-empty line
# set the flag to begin printing lines
p=1
# print the accumulated "interior" empty lines
for (i=1; i<=n; i++) print ""
n=0
# then print this line
print
}
p && /^[[:space:]]*$/ {
# a potentially "interior" empty line. remember it.
n++
}
' filename
注意してください。空の/空でない行を検討するために使用しているメカニズムのため( [[:graph:]]
と /^[[:space:]]*$/
)、空白のみを備えた内部ラインは、本当に空になるように切り捨てられます。
awkの使用:
awk '{a[NR]=$0;if($0 && !s)s=NR;}
END{e=NR;
for(i=NR;i>1;i--)
if(a[i]){ e=i; break; }
for(i=s;i<=e;i++)
print a[i];}' yourFile
で述べたように 別の答え, tac
Coreutilsの一部です, 、およびファイルを逆にします。それを2回行うというアイデアを組み合わせる コマンド代替がトレーリングの新しい行を剥奪するという事実, 、 我々が得る
echo "$(echo "$(tac "$filename")" | tac)"
それに依存しません sed
. 。使用できます echo -n
残りのトレーリングニューラインを取り除きます。
これが適応されたSEDバージョンです。これは、スペースとタブだけが付いた「空の」行を「空」と見なしています。
sed -e :a -e '/[^[:blank:]]/,$!d; /^[[:space:]]*$/{ $d; N; ba' -e '}'
それは基本的に受け入れられた回答バージョンです(Bryanhのコメントを考慮して)が、ドット .
最初のコマンドではに変更されました [^[:blank:]]
(空白ではないもの)と \n
2番目のコマンドアドレスの内部はに変更されました [[:space:]]
Newlinesを許可するには、タブをスペースにします。
POSIXクラスを使用せずに代替バージョンですが、SEDは挿入をサポートする必要があります \t
と \n
中身 […]
. 。 GNU SEDは、BSD SEDはそうではありません。
sed -e :a -e '/[^\t ]/,$!d; /^[\n\t ]*$/{ $d; N; ba' -e '}'
テスト:
prompt$ printf '\n \t \n\nfoo\n\nfoo\n\n \t \n\n'
foo
foo
prompt$ printf '\n \t \n\nfoo\n\nfoo\n\n \t \n\n' | sed -n l
$
\t $
$
foo$
$
foo$
$
\t $
$
prompt$ printf '\n \t \n\nfoo\n\nfoo\n\n \t \n\n' | sed -e :a -e '/[^[:blank:]]/,$!d; /^[[:space:]]*$/{ $d; N; ba' -e '}'
foo
foo
prompt$
使用 bash
$ filecontent=$(<file)
$ echo "${filecontent/$'\n'}"
Bashでは、猫、WC、グレップ、SED、尾、頭を使用してください:
# number of first line that contains non-empty character
i=`grep -n "^[^\B*]" <your_file> | sed -e 's/:.*//' | head -1`
# number of hte last one
j=`grep -n "^[^\B*]" <your_file> | sed -e 's/:.*//' | tail -1`
# overall number of lines:
k=`cat <your_file> | wc -l`
# how much empty lines at the end of file we have?
m=$(($k-$j))
# let strip last m lines!
cat <your_file> | head -n-$m
# now we have to strip first i lines and we are done 8-)
cat <your_file> | tail -n+$i
男、そのugさを避けるために「本当の」プログラミング言語を学ぶことは間違いなく価値があります!
Trailing Newlinesストリップ(「白い」文字を含む)の効率的な非再帰バージョンのために、私はこれを開発しました sed
脚本。
sed -n '/^[[:space:]]*$/ !{x;/\n/{s/^\n//;p;s/.*//;};x;p;}; /^[[:space:]]*$/H'
ホールドバッファーを使用してすべての空白線を保存し、非ブランクラインを見つけた後にのみ印刷します。誰かがニューラインだけを望んでいるなら、それは2つを取り除くのに十分です [[:space:]]*
部品:
sed -n '/^$/ !{x;/\n/{s/^\n//;p;s/.*//;};x;p;}; /^$/H'
よく知られている再帰スクリプトとの簡単なパフォーマンス比較を試みました
sed -e :a -e '/^\n*$/{$d;N;};/\n$/ba'
ランダムなBase64テキストの周りに1MBのランダムな空白線を備えた3MBファイル。
shuf -re 1 2 3 | tr -d "\n" | tr 123 " \t\n" | dd bs=1 count=1M > bigfile
base64 </dev/urandom | dd bs=1 count=1M >> bigfile
shuf -re 1 2 3 | tr -d "\n" | tr 123 " \t\n" | dd bs=1 count=1M >> bigfile
ストリーミングスクリプトは完了するまでに約0.5秒かかりましたが、再帰は15分後に終了しませんでした。勝つ :)
答えを完全にするために、SEDスクリプトを削除する主要な行はすでに正常にストリーミングされています。あなたに最も適したものを使用してください。
sed '/[^[:blank:]]/,$!d'
sed '/./,$!d'
a bash
解決.
注:便利なだけです ファイルが十分に小さい場合 一度にメモリに読み込む。
[[ $(<file) =~ ^$'\n'*(.*)$ ]] && echo "${BASH_REMATCH[1]}"
$(<file)
ファイル全体を読み取り、トリミングします トレーリング newlines、コマンド代替($(....)
) 暗黙的に それをします。=~
バッシュです 通常の発現マッチング演算子, 、 と=~ ^$'\n'*(.*)$
オプションで任意と一致します リーディング Newlines(貪欲に)、そして後に来るものは何でもキャプチャします。潜在的に混乱を招くことに注意してください$'\n'
, 、リテラルニューラインを使用して挿入します ansi c quoing, 、エスケープシーケンスです\n
サポートされていません。- この特定の正規表現に注意してください いつも 一致するので、コマンドは後
&&
は いつも 実行された。 - 特別な配列変数
BASH_REMATCH
再戦には、最新の正規表現マッチと配列要素の結果が含まれています[1]
(最初と唯一の)括弧付きのサブエグジュレーション(キャプチャグループ)がキャプチャしたものが含まれています。正味の効果はそれです${BASH_REMATCH[1]}
削除されたリーディングとトレーリングの両方のニューラインの両方を備えた入力ファイルコンテンツが含まれています。 - で印刷することに注意してください
echo
単一のトレーリングニューラインを追加します。それを避けたい場合は、使用してくださいecho -n
代わりに(またはより多くのポータブルを使用しますprintf '%s'
).
別のバリアントを紹介したいと思います Gawk V4.1+
result=($(gawk '
BEGIN {
lines_count = 0;
empty_lines_in_head = 0;
empty_lines_in_tail = 0;
}
/[^[:space:]]/ {
found_not_empty_line = 1;
empty_lines_in_tail = 0;
}
/^[[:space:]]*?$/ {
if ( found_not_empty_line ) {
empty_lines_in_tail ++;
} else {
empty_lines_in_head ++;
}
}
{
lines_count ++;
}
END {
print (empty_lines_in_head " " empty_lines_in_tail " " lines_count);
}
' "$file"))
empty_lines_in_head=${result[0]}
empty_lines_in_tail=${result[1]}
lines_count=${result[2]}
if [ $empty_lines_in_head -gt 0 ] || [ $empty_lines_in_tail -gt 0 ]; then
echo "Removing whitespace from \"$file\""
eval "gawk -i inplace '
{
if ( NR > $empty_lines_in_head && NR <= $(($lines_count - $empty_lines_in_tail)) ) {
print
}
}
' \"$file\""
fi
@Dogbaneには、主要な空のラインを削除するための素晴らしい簡単な答えがあります。これは、トレーリングラインだけを削除する単純なawkコマンドです。これを @DogbaneのSEDコマンドで使用して、先頭のブランクとトレーリングブランクの両方を削除します。
awk '{ LINES=LINES $0 "\n"; } /./ { printf "%s", LINES; LINES=""; }'
これは非常に簡単です。
- 読みながら、すべての行をバッファーに追加します。
- 文字を含むすべての行について、バッファの内容を印刷してからクリアします。
したがって、バッファリングされて表示されないのは、後続のブランクだけです。
newlinesを使用してバッファー内のラインを既に分離するため、新線の自動追加を避けるために印刷の代わりにprintfを使用しました。
このAWKスクリプトだという:
BEGIN {
ne=0;
}
/^[[:space:]]*$/ {
ne++;
}
/[^[:space:]]+/ {
for(i=0; i < ne; i++)
print "";
ne=0;
print
}
することができ:空行はなく響きます。そうではなく、また空線なければいけないのですが、まずエコーとして多くの空行としてのみでなければいけないのですが、エコーの新しい空です。
perl -0pe 's/^\n+|\n+(\n)$/\1/gs'