2つの単語間の特定の文字をCR + LFに置き換える方法

2つの単語間の特定の文字をCR + LFに置き換える方法

どのサーバーに特定のファイルと所有権があるかを知らせるcsvファイルを生成したいと思います。これは私が得る生の出力です。

server01,server02,server03,owner,/etc/file1
server04,owner,/etc/file2
server05,server06,owner,/etc/file3

サーバー名間のカンマをWindows形式の改行(CF + LR)に変更し、その間に引用符を追加して、CSVに同じボックスにすべてのサーバーを表示させたいと思います。

希望の出力:

"server01
server02
server03",owner,/etc/file1
"server04",owner,/etc/file2
"server05
server06",owner,/etc/file3

これを達成するためにsedを使用する方法は?

ベストアンサー1

,owner,フィールドにラップする残りのテキストがすべてある場合:

GNUの使用sed:

sed -E ':1; s/,(.*,owner,)/\r\n\1/; t1; s/(.*)(,owner,)/"\1"\2/' file

そしてperl

perl -pe 's{.*?(?=,owner,)}{q(") . ($& =~ s/,/\r\n/gr) . q(")}e' file

最後の2つのフィールドを除くすべての項目がある場合:

GNUの使用sed:

sed -E ':1; s/(.*),(.*,.*,)/\1\r\n\2/; t1; s/(.*),/"\1",/' file

そしてperl

perl -pe 's{(.*)(?=,.*,)}{q(") . ($& =~ s/,/\r\n/gr) . q(")}e' file

または、Text::CSV正しいCSVの解析とフォーマットのためにPerlモジュールを使用してください。

perl -MText::CSV -e '
  $csv = Text::CSV->new({binary => 1, decode_utf8 => 0, eol => $" = "\r\n"});
  while ($row = $csv->getline(STDIN)) {
    if (($last = $#{$row}) > 1) {
      $csv->print(STDOUT, ["@$row[0..$last-2]", @$row[$last-1..$last]]);
    } else {
      $csv->print(STDOUT, $row);
    }
  }' < file

ファイルがBOMでUTF-16またはUTF-8でエンコードされている場合(Microsoftファイルでは前例のない作業)、調整する必要があります(この方法については参考資料を参照)、何らかの方法でエンコードする必要があります。通常の入力を処理できるようにperldoc Text::CSVフォーマットを再指定する方法です。<file dos2unix | ... | unix2dos

おすすめ記事