
カンマ()で区切られた入力ファイルがあります,
。一部のフィールドはカンマで二重引用符で囲まれています。サンプルラインです
123,"ABC, DEV 23",345,534.202,NAME
二重引用符だけでなく、二重引用符内のすべてのカンマを削除する必要があります。したがって、上記の行は次のように解析する必要があります。
123,ABC DEV 23,345,534.202,NAME
次の使用法を試しましたが、sed
期待した結果が得られませんでした。
sed -e 's/\(".*\),\(".*\)/\1 \2/g'
sed
それとも、awk
他のUNIXユーティリティに関するクイックヒントはありますか?
答え1
awk
引用文のバランスが取れたら、次のように表すことができる引用符の間のカンマを削除する必要があります。
awk -F'"' -v OFS='' '{ for (i=2; i<=NF; i+=2) gsub(",", "", $i) } 1' infile
出力:
123,ABC DEV 23,345,534.202,NAME
説明する
二重引用符でフィールド分割を実行するようにawkに指示します-F"
。これは、他のすべてのフィールドが引用符で囲まれたテキストであることを意味します。 forループはgsub
他のすべてのフィールドで動作します。グローバル置換の省略形として、","
カンマ()を空(""
)に置き換えます。最後に、1
基本コードブロックを呼び出します{ print $0 }
。
答え2
一つあるいいね回答、sedを一度だけ使用してくださいリング:
echo '123,"ABC, DEV 23",345,534,"some more, comma-separated, words",202,NAME'|
sed ':a;s/^\(\([^"]*,\?\|"[^",]*",\?\)*"[^",]*\),/\1 /;ta'
123,"ABC DEV 23",345,534,"some more comma-separated words",202,NAME
説明する:
:a;
追加ポイントのラベルです。s/^\(\([^"]*,\?\|"[^",]*",\?\)*"[^",]*\),/\1 /
3つの閉鎖部品を含めることができます。- 最初の2番目:
[^"]*,\?\|"[^",]*",\?
二重引用符を含めずにコンマが後に続く可能性がある文字列と一致します。またはカンマなしで2つの二重引用符で囲まれた文字列で、後にカンマが続くこともあります。 - 最初のものより希土類部分前述のパート2の複数の反復で構成され、その後に二重引用符といくつかの文字が続きますが、二重引用符とカンマはありません。
- 最初のRE部分の後には昏睡状態が続きます。
- 残りの行に触れる必要はありません。
- 最初の2番目:
ta
:a
前s/
のコマンドが一部変更された場合は繰り返されます。
ループが完了したら、以下を追加することもできますs/ */ /g
。
echo '123,"ABC, DEV 23",345,534,"some more, comma-separated, words",202,NAME'|
sed ':a;s/^\(\([^"]*,\?\|"[^",]*",\?\)*"[^",]*\),/\1 /;ta;s/ */ /g'
二重スペースを抑制します。
123,"ABC DEV 23",345,534,"some more comma-separated words",202,NAME
答え3
バランスの取れた引用符間の複数のカンマも処理する一般的なソリューションには、入れ子になった置換が必要です。私は与えられた入力の各行を処理し、他のすべての引用符ペアのコンマだけを置き換えるソリューションをPerlとして実装しました。
perl -pe 's/ " (.+? [^\\]) " # find all non escaped
# quoting pairs
# in a non-greedy way
/ ($ret = $1) =~ (s#,##g); # remove all commas within quotes
$ret # substitute the substitution :)
/gex'
または簡単に言えば
perl -pe 's/"(.+?[^\\])"/($ret = $1) =~ (s#,##g); $ret/ge'
処理するテキストをコマンドにパイプするか、最後のコマンドライン引数として処理するテキストファイルを指定できます。
答え4
2番目の参照が間違っています。
sed -e 's/\(".*\),\(.*"\)/\1 \2/g'
また、正規表現を使用すると、テキストの可能な最長部分に一致する傾向があります。つまり、文字列に引用符で囲まれた複数のフィールドがある場合、この方法は機能しません。
sedで複数の参照フィールドを処理する方法
sed -e 's/\(\"[^",]\+\),\([^",]*\)/\1 \2/g' -e 's/\"//g'
これはこの問題を解決する方法でもあります。ただし、参照される各フィールドに複数のカンマを含めることができる入力の場合、sedの最初の式は、単一フィールドの最大コンマ内容と同じくらい変更されるまで繰り返す必要があります。出力がまったく。
複数の式でsedを実行することは、複数のsedプロセスを実行し、すべての「tr」をオープンパイプとして実行するよりも効率的です。
ただし、入力形式が正しくないと、望ましくない結果が生じる可能性があります。つまり、入れ子になった引用符、終わらない引用符です。
実行例の使用:
echo '123,"ABC, DEV 23",345,534,"some more, comma-separated, words",202,NAME' \
| sed -e 's/\(\"[^",]\+\),\([^",]*\)/\1 \2/g' \
-e 's/\(\"[^",]\+\),\([^",]*\)/\1 \2/g' -e 's/\"//g'
出力:
123,ABC DEV 23,345,534,some more comma-separated words,202,NAME