メモを取るために使用するテキストファイルがいくつかあります。通常はcat >> file
。時々、空白の行を1つまたは2つ使用して(改行文字を返すだけで)、新しい件名/思考の行を指定します。各セッションの最後に、ファイルを閉じる前に Ctrl+D、私は通常、セッションを区切るために、たくさん(5-10)の空白行(リターンキー)を追加します。
これは明らかに賢明ではありませんが、この目的のために私にとってはうまくいきます。私はdoですが、不要な空白行がたくさんあるので、余分な行(のほとんど)を削除する方法を探しています。いくつかのオプションで直接使用できるLinuxコマンド(カット、ペースト、grepなど)はありますか?あるいは、誰かが私が望むことをするsed、awk、またはPerl(実際にはsedまたはawkの方が好きですが、スクリプト言語では十分です)のアイデアを持っていますか? C++で何かを書いて(実際は自分でできる)、やり過ぎのように思えます。
ケース#1:必要なのは、2つ以上(3つ以上)の連続する空白行を削除し、それらを2つだけの空白行に置き換えるスクリプト/コマンドです。ただし、複数の行(2行以上)を削除したり、複数の空白行を1行だけに置き換えたりすることもできます。
ケース#2:2行のテキスト間のsingle空白行を削除するスクリプト/コマンドを使用することもできますが、複数の空白行をそのまま残します(空白行の1つを削除することもできます)許容)。
ケース1:
awk '!NF {if (++n <= 2) print; next}; {n=0;print}'
ケース2:
awk '!NF {s = s $0 "\n"; n++; next}
{if (n>1) printf "%s", s; n=0; s=""; print}
END {if (n>1) printf "%s", s}'
uniq
を使用すると、空白行の複数のインスタンスを1つの空白行に折りたたむことができますが、テキストが同じで互いに下にある場合、テキストを含む行も折りたたまれます。
ケース1:
Perl -i -ane '$n=(@F==0) ? $n+1 : 0; print if $n<=2'
ケース2:
Perl -i -ane '$n=(@F==0) ? $n+1 : 0; print $n==2 ? "\n$_" : $n==1 ? "" : $_ '
GNU sed:
sed -r ':a; /^\s*$/ {N;ba}; s/( *\n *){2,}/\n\n/'
つまり、パターンスペース内の空の行を収集し、3行以上ある場合は2行に減らします。
ケース#2のようにシングルスペース行を結合するには、次のようにします。
sed -r '/^ *\S/!b; N; /\n *$/!b; N; /\S *$/!b; s/\n *\n/\n/'
またはコメント形式で:
sed -r '
/^ *\S/!b # non-empty line
N #
/\n *$/!b # followed by empty line
N #
/\S *$/!b # non-empty line
s/\n *\n/\n/ # remove the empty line
'
投稿された解決策は私には少し不可解に見えました。これはPython 3.6の解決策です:
#!/usr/bin/env python3
from pathlib import Path
import sys
import fileinput
def remove_multiple_blank_lines_from_file(path, strip_right=True):
non_blank_lines_out_of_two_last_lines = [True, True]
for line in fileinput.input(str(path), inplace=True):
non_blank_lines_out_of_two_last_lines.pop(0)
non_blank_lines_out_of_two_last_lines.append(bool(line.strip()))
if sum(non_blank_lines_out_of_two_last_lines) > 0:
line_to_write = line.rstrip() + '\n' if strip_right else line
sys.stdout.write(line_to_write)
def remove_multiple_blank_lines_by_glob(rglob='*', path=Path('.'), strip_right=True):
for p in path.rglob(rglob):
if p.is_file():
try:
remove_multiple_blank_lines_from_file(p, strip_right=strip_right)
except Exception as e:
print(f"File '{p}' was not processed due the error: {e}")
if __name__ == '__main__':
remove_multiple_blank_lines_by_glob(sys.argv[1], Path(sys.argv[2]), next(iter(sys.argv[3:]), None) == '--strip-right')
次のように、インタープリターから関数を呼び出すか、シェルから実行できます。
$ ./remove_multiple_lines.py '*' /tmp/ --strip-right
Anthon が「uniq」を使用するよう提案しています...
先頭、末尾、重複する空白行を削除します。
# Get large random string.
Rand_str=; while [[ ${#Rand_str} -lt 40 ]]; do Rand_str=$Rand_str$RANDOM; done
# Add extra lines at beginning and end of stdin.
(echo $Rand_str; cat; echo $Rand_str) |
# Convert empty lines to random strings.
sed "s/^$/$Rand_str/" |
# Remove duplicate lines.
uniq |
# Remove first and last line.
sed '1d;$d' |
# Convert random strings to empty lines.
sed "s/$Rand_str//"
一行で:
(Rand_str=; while [[ ${#Rand_str} -lt 40 ]]; do Rand_str=$Rand_str$RANDOM; done; (echo $Rand_str; cat; echo $Rand_str) | sed "s/^$/$Rand_str/" | uniq | sed '1d;$d' | sed "s/$Rand_str//")
または単に「cat -s」を使用します。
現在のシェルコンテキスト のままにするために、括弧から中括弧に切り替えました。中括弧は、最後のコマンドの後にセミコロンが必要であり、区切るためのスペースが必要であることに注意してください。
# Add extra blank lines at beginning and end.
# These will be removed in final step.
{ echo; cat; echo; } |
# Replace multiple blank lines with a single blank line.
cat -s |
# Remove first and last line.
sed '1d;$d'
1行で。
{ { echo; cat; echo; } | cat -s | sed '1d;$d'; }