web-dev-qa-db-ja.com

空の行を削除するためにテキストファイルをフィルタリングする良い方法は何ですか?

空の行がたくさんある.csvファイル(Macの場合)があります。例:

"1", "2", "lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum 

lorem ipsum ","2","3","4"
"1", "2", "lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum 

lorem ipsum ","2","3","4"

変換したいもの:

"1", "2", "lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum ","2","3","4"
"1", "2", "lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum  lorem ipsum ","2","3","4"

ライナーが1つあるはずですが、awkやsedはわかりません。ヒントは大歓迎です!

11
pitosalas

ファイルを提供した方が簡単だったはずですが、残念ながら、共有できない機密情報が含まれていました。その間に私は私にRubyスクリプトを書いたが、それはトリックをしているようだった:

require 'csv'
c = CSV.open("outfile1.csv", "w")
CSV.foreach("data.csv", :encoding => 'windows-1251:utf-8') do |row|
  row = row.map { |a| a.class == String ? a.gsub(/\r/, '') : a}
  c << row
end
c.close

助けてくれてありがとう!

3
pitosalas

これを行うには、grepの-v(一致を反転)モードを使用できます。

grep -v '^$' old-file.csv > new-file.csv

シェルリダイレクトの仕組みのため、これらは異なるファイルである必要があることに注意してください。入力ファイルが読み取られる前に、出力ファイルが開かれます(そして空にされます)。 moreutils(Mac OS Xではデフォルトではない)がある場合は、spongeを使用してこれを回避できます。

grep -v '^$' file.csv | sponge file.csv

しかし、もちろん、何か問題が発生した場合、戻るのが難しくなります。

「空白行」に実際にスペースが含まれている可能性がある場合は(空白のように聞こえます)、代わりにこれを使用できます。

egrep -v '^[[:space:]]*$' old-file.csv > new-file.csv

これは、空白行と空白のみを含む行を無視します。もちろん、同じsponge変換を実行できます。

11
derobert

最も簡単なオプションはgrep .。ここで、ドットは「何にでも一致する」という意味なので、行が空の場合は一致しません。それ以外の場合は、行全体をそのまま印刷します。

8
Onturenio

空の行を削除するには、インプレース、ksh93を使用:

sed '/./!d' file 1<>; file

<>;リダイレクト演算子はksh93に固有であり、コマンドの終了後にkshがファイルを切り捨てることを除いて、標準の<>演算子と同じです。

sed '/./!d'grep .を書くための複雑な方法ですが、残念ながらGNU grepは、stdoutがstdinと同じファイルを指している場合、少なくとも文句を言います。書くことができます:

grep . file | cat 1<>; file

しかし残念ながら、ksh93(少なくとも私のバージョン(93u +))にはバグがあり、その場合、ファイルは長さがゼロに切り捨てられているようです。

grep . file | { cat; } 1<>; file

そのバグを回避するようですが、今では、sedコマンドよりもはるかに複雑です。

6

以下がPerlの1行です:

Perl -pi -e 's/^\s*\n//' yourfile

編集:以下のruakhのコメントに基づいてコードを改善しました。

5
Joseph R.

あなたの質問へのコメントの説明に基づいて、次のようなものがあります。

awk -v RS= -v ORS= 1

あなたがやりたいことをするかもしれません。

空のレコード区切り文字は、レコードが段落(空の行のシーケンスで区切られる)であることをawkに通知する特殊なケースです。 出力レコード区切り記号を空の文字列に設定すると、それらの段落の内容(区切り記号なし)が連結されます。 1は、すべてのレコードを印刷するための単なるtrue条件です。

ただし、末尾の改行は省​​略されるため、次のようにできます。

awk -v RS= -v ORS= '1;END{if (NR) printf "\n"}'
5

stackoverflow で可能な解決策のアイデアを見つけました。

sed -i ':a;N;$!ba;s/[^"]\n\s*\n/ /g' file.csv

テストする前にcsvファイルをバックアップする必要がありますが、少なくとも提供した例では問題なく動作します。

この式の内部動作についての良い説明が答えにあります。私はそれを編集して、"[^"]\n)で終わらない行を探しました。

2
tongpu
awk '
    length == 0 {next} 
    /^[^"]/ && /"$/ {print; next} 
    {printf("%s", $0)}
' filename

作り出す

"1", "2", "lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum ","2","3","4"
"1", "2", "lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum ","2","3","4"
2
glenn jackman

あなた自身の応答から、引用符で囲まれた文字列内に含まれる改行文字を削除したい場合は、次のようにすることができます:

 Perl -0777 -pe 's/".*?"/$_=$&;s:\n::g;$_/gse'

Perlの-iフラグを使用して、ファイルを編集することもできますインプレース

 Perl -0777 -pe 's/".*?"/$_=$&;s:\n::g;$_/gse' file1 file2...

またはGNU awk:

 awk -v RS=\" 'NR%2==0 {gsub("\n","")}; {printf "%s", $0 RT}'

または:

 awk -vRS=\" '1-NR%2{gsub("\n","")}{ORS=RT}1'

(最短のものを求めて競争している場合)

これらは、入力にescaped二重引用符がないことを前提としていることに注意してください。

1

VimはExモードで使用できます。

ex -sc v/./d -cx b.csv
  1. v/./空の行を見つける

  2. d削除

  3. x保存して閉じる

0
Steven Penny

AWKの空行を削除する方法はこれまでになく短くなっています。

_awk 'NF' file_

しかし、必要な出力を得るには、単純な1つのライナーが必要です。

awk 'NF {printf("%s ", $0); i++;} !(i % 2) {printf("\n");}' file

説明

AWKでは、空の行は行/レコードにフィールドがないことを意味します。つまり、NF(フィールド数)変数はゼロです。上記の1つのライナーは、_NF > 0_の場合にのみ実行され、すべての行を印刷しますが、空の行は印刷します。

_i++_は、空でない行カウンターです。

!(i % 2)は、2つの連続する空でない行を目的の出力の方法で出力するために使用されます。つまり、2の倍数が見つかるたびに、moduloステートメント!(i % 2)は1を生成し、2つの空でない行の連結を終了します。

0
Marcelo Augusto

事実上、空の行を削除する以上のことが必要であるように見えますが、2つ以上の改行文字のすべてのシーケンスを削除します。

Perlでできること:

Perl -0777 -pe 's/\n{2,}//gs' file

Perlの-iフラグを使用して、ファイルを編集することもできますインプレース

Perl -0777 -pi -e 's/\n{2,}//gs' file1 file2...
0