各列の後にカンマを追加するには?

各列の後にカンマを追加するには?

Excelで.csvを開くときに各列に独自のタブがあるようにするには、これが必要です。

私のテキストは次のとおりです。

smmsp              Purpose - Service account for Sendmail; Owner - sysadmin; SERVICE ACCOUNT                            n    Account expires : never
samba              Purpose - Service account for Samba; Owner - sysadmin; SERVICE ACCOUNT                               n    Account expires : never
puppet             Purpose - Service account for Puppet; Owner - sysadmin; SERVICE ACCOUNT                              n    Account expires : never

私はこれが必要です:

smmsp,              Purpose - Service account for Sendmail; Owner - sysadmin; SERVICE ACCOUNT,                            n,    Account expires : never,
samba,              Purpose - Service account for Samba; Owner - sysadmin; SERVICE ACCOUNT,                               n,    Account expires : never,
puppet,             Purpose - Service account for Puppet; Owner - sysadmin; SERVICE ACCOUNT,                              n,    Account expires : never,

出力をパイピングしようとしましたが、awk 'gsub(" ", ",", $1)' FS=, OFS=,すべてのスペースがコンマで置き換えられました。

答え1

入力ファイルが固定幅形式のようです。 Excelで開いて変更せずに各列の位置を指定できる必要があります。

ただし、入力例のすべてのフィールドには少なくとも2つ以上のスペースが含まれているように見えるため、2つ以上のスペースがあるすべての項目をコンマで置き換えることができます。

sed -r 's/  \+/,/g' input.txt

指示:

  • 上記-rには、GNUのsedで使用できる拡張正規表現()が必要です。
  • テキストフィールドが固定幅フィールドを埋めるのに十分な長さまたはスペースが1つだけ残っている場合、コンマは挿入されません。

固定幅フィールドの末尾にカンマを入れてから、余分なスペースを削除する別の方法があります。この例では、固定幅フィールドの幅は入力の例に基づいています。

sed 's/\(.\{19\}\)\(.\{101\}\)\(.\{5\}\)/\1,\2,\3,/' columns.txt | sed 's/ *,/,/g'

後者のアプローチは正規表現を拡張する必要はなく、アイテムが完全な固定幅フィールドを満たす場合にも機能します。

答え2

内部間隔を維持したいと思うので、@cherdtの解決策と同様のことを行いますが、次のようなことをキャプチャできます。

sed -e 's/\(  \+\)/,\1/g' input

これにより、スペースの数を変更せずに、2つ以上のスペースで構成される各ブロックの前にコンマが配置されます。

答え3

列がタブで区切られている場合(次のように表示されます)、次のように機能します。

$awk -F "[\t]*" '{print $1", "$2", "$3", "$4", "}' b.txt
smmsp, Purpose - Service account for Sendmail; Owner - sysadmin; SERVICE ACCOUNT, n, Account expires : never, 

列がタブではなくスペースで区切られている場合、スペースを区切り文字として使用すると、データ間にスペースがあるため、少し混乱する可能性があります。

ファイルを読み取り、次の配列に保存します。

$while IFS=" " read -a line;do for i in {0,11,12,16};do line[$i]+=",";done;echo "${line[@]}";done <b.txt
smmsp, Purpose - Service account for Sendmail; Owner - sysadmin; SERVICE ACCOUNT, n, Account expires : never,
smmsp, Purpose - Service account for Sendmail; Owner - sysadmin; SERVICE ACCOUNT, n, Account expires : never,
smmsp, Purpose - Service account for Sendmail; Owner - sysadmin; SERVICE ACCOUNT, n, Account expires : never,
smmsp, Purpose - Service account for Sendmail; Owner - sysadmin; SERVICE ACCOUNT, n, Account expires : never,
smmsp, Purpose - Service account for Sendmail; Owner - sysadmin; SERVICE ACCOUNT, n, Account expires : never,

空間分離の観点から、配列要素line[0]、line[11]、line[12]、line[16]にカンマを追加する必要があることがわかりました。

このトリックを使用するには、すべての行の形式が同じでなければなりません。
そうでない場合は、各配列要素を読み、必要な場所にコンマを挿入する必要があります。

行が多く、パフォーマンスを重視している場合は、awkスクリプトを作成してすべての変数($ 1から$ NFまで)を同じように処理できますが、awkスクリプトの内部では(私はawkがうまくいきません。)

関連情報