一部のフィールドが引用符で囲まれたCSVファイルがあり、引用符内の項目は二重スペースまたは単一スペースで区切られています。カンマに置き換える必要があります。
例示ライン:
This is okay,"ABC DEF GHI",123,"This is not okay",remove,spaces,within,quotes
そしてそれはどのように見えるべきですか:
This is okay,"ABC,DEF,GHI",123,"This,is,not,okay",remove,spaces,within,quotes
答え1
perl -pe 's/".*?"/do{$a = $&; $a =~ s: +:,:g; $a}/ge;'
基本的にこれは単なるグローバル正規表現の置換ですs/regex/replacement/g
。正規表現は、".*?"
次から始まり終わるすべての部分文字列と一致することです。トリッキーな部分は次のとおりです。"
"
- 置き換えられるのは、文字列ではなく計算された式です。 (これは
e
次の修飾子の意味ですg
。) s:regex:replacement:g
評価された式は、空でない空白シーケンスをコンマで置き換えるグローバル正規表現の置換です。 (外部置換と同じ区切り文字を使用できないため、代わりに:
使用します/
。)- 内部正規表現置換を実行するには、外部置換の一致する部分文字列を
$&
別の変数に割り当ててから、$a
内部置換を実行して$a
最後に印刷する必要があります$a
。
まったく新しいバージョンの Perl では、補助変数への割り当てを避けることができます。修飾子を使用すると、一致する部分r
文字列のコピーから直接内部置換を実行できます$&
(Stéphane Chazelasのおかげで)。
perl -pe 's/".*?"/$&=~s: +:,:gr/ge;'
答え2
この無差別代入ソリューションを検討してください。
awk -F, -v OFS=, '
{
for(i=1;i<=NF;i++)
if ($i ~ /^".*"$/)
gsub(" +", ",", $i)
print $0
}'
awk にレコードをコンマに分割するように指示します。フィールドにカンマが含まれていると、これが壊れる可能性があることに注意してください。 - そして、OFSを使用して印刷ステートメントにフィールドをカンマで再グループ化するように指示します。for
行の各フィールドを繰り返し、フィールドが^
二重引用符で始まり、すべての文字を含み、.*
二$
重引用符で終わると、グローバル$i
にフィールドのすべてのスペースをコンマで置き換えます。フィールドを繰り返した後、レコード全体を印刷します($0
)。
答え3
GNUの使用awk
:
gawk -v RS=\" '
NR % 2 == 0{gsub(/ +/, ",")}
{ORS = RT; print}'
つまり、レコード区切り文字は、偶数"
レコードでのみ文字とスペースを置き換えます。
RT
GNU 特定の部分です。
GNUと同じsed
:
tr '\n"' '"\n' | sed -E '2~2s/ +/,/g' | tr '"\n' '\n"'
携帯性が向上しました。
tr '\n"' '"\n' | sed 'n;s/ */,/g' | tr '"\n' '\n"'
他のsed
sで使用できますが、入力した最後の文字がそうでない場合は、問題が発生する可能性があります"
。