空の行がたくさんある.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はわかりません。ヒントは大歓迎です!
ファイルを提供した方が簡単だったはずですが、残念ながら、共有できない機密情報が含まれていました。その間に私は私に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
助けてくれてありがとう!
これを行うには、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
変換を実行できます。
最も簡単なオプションはgrep .
。ここで、ドットは「何にでも一致する」という意味なので、行が空の場合は一致しません。それ以外の場合は、行全体をそのまま印刷します。
空の行を削除するには、インプレース、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コマンドよりもはるかに複雑です。
以下がPerl
の1行です:
Perl -pi -e 's/^\s*\n//' yourfile
編集:以下のruakhのコメントに基づいてコードを改善しました。
あなたの質問へのコメントの説明に基づいて、次のようなものがあります。
awk -v RS= -v ORS= 1
あなたがやりたいことをするかもしれません。
空のレコード区切り文字は、レコードが段落(空の行のシーケンスで区切られる)であることをawk
に通知する特殊なケースです。 出力レコード区切り記号を空の文字列に設定すると、それらの段落の内容(区切り記号なし)が連結されます。 1
は、すべてのレコードを印刷するための単なるtrue条件です。
ただし、末尾の改行は省略されるため、次のようにできます。
awk -v RS= -v ORS= '1;END{if (NR) printf "\n"}'
stackoverflow で可能な解決策のアイデアを見つけました。
sed -i ':a;N;$!ba;s/[^"]\n\s*\n/ /g' file.csv
テストする前にcsvファイルをバックアップする必要がありますが、少なくとも提供した例では問題なく動作します。
この式の内部動作についての良い説明が答えにあります。私はそれを編集して、"
([^"]\n
)で終わらない行を探しました。
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"
あなた自身の応答から、引用符で囲まれた文字列内に含まれる改行文字を削除したい場合は、次のようにすることができます:
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二重引用符がないことを前提としていることに注意してください。
VimはExモードで使用できます。
ex -sc v/./d -cx b.csv
v/./
空の行を見つける
d
削除
x
保存して閉じる
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つの空でない行の連結を終了します。
事実上、空の行を削除する以上のことが必要であるように見えますが、2つ以上の改行文字のすべてのシーケンスを削除します。
Perlでできること:
Perl -0777 -pe 's/\n{2,}//gs' file
Perlの-i
フラグを使用して、ファイルを編集することもできますインプレース。
Perl -0777 -pi -e 's/\n{2,}//gs' file1 file2...