シェルスクリプトを使用してcsvの2行目をテキスト処理し、処理された特定の行の結果をCSVの新しい列に追加するにはどうすればよいですか?

シェルスクリプトを使用してcsvの2行目をテキスト処理し、処理された特定の行の結果をCSVの新しい列に追加するにはどうすればよいですか?
filename~contenturl~uuid~nodeid~contentid

000224.pdf~store://2018/7/20/11/35/3f176f4b-41a0-4ac4-a795-a2240ffbb7b9.bin~d6203724-1100-4057-9ed5-4ca6a94f5512~1324625~1363256
000238.pdf~store://2018/7/20/11/35/4302b390-1134-424d-a92f-ad27b233e8c1.bin~96b7343d-349d-4316-8bc6-def5bd924032~1324641~1363292
000262.pdf~store://2018/7/20/11/35/5ff59679-b3ec-46d2-aa7d-5ec28eff6fe9.bin~11827eee-67bb-43b7-a743-966514f26457~1324661~1363375

上記は、区切り文字 "〜"を持つ.csvファイルです。 store://で始まる2番目の列の部分文字列を作成し、その行のチェックサム結果を同じ列に追加しようとしています。新しい列は、可能であればCSVを使用します。

例えば

filename~contenturl~checksum
000224.pdf  /opt/xyz/2018/7/20/11/35/3f176f4b-41a0-4ac4-a795-a2240ffbb7b9.bin  23423423425

したがって、最終結果が表示されたら、store://のパス部分文字列を作成し、そのファイルのチェックサムという新しい列を追加します。

シェルスクリプトでbin / bashを使用したい

========================私の場合は、今AWKを試してみましたが、次のようにして最初と2番目の列値のみを取得できました。

awk -F "~" '{print $1, $2}'  $csv_file

今、次のタスクは複雑です。 2番目の列値にはテキスト処理が必要です。チェックサムあなたは合格できます

cksum /opt/xyz/2018/7/20/11/35/3f176f4b-41a0-4ac4-a795-a2240ffbb7b9.bin

はい、ちゃんと聞きました。最終結果は次のとおりです。

filename~contenturl~checksum
000224.pdf  /opt/xyz/2018/7/20/11/35/3f176f4b-41a0-4ac4-a795-a2240ffbb7b9.bin  23423423425

他の列の残りの部分もあれば良いでしょう。それ以外の場合は、上位3列も問題ありません。 注:既存の列を維持し、「チェックサム」という列を追加してもかまいません。

答え1

回避策を少し簡単にし、ヘッダー行が一貫していないため(入力ファイルの改行が間違っていて出力ファイルの区切り文字が間違っている~)、入力ファイルにヘッダー行がないとしましょう。

これは次の2つのステップで解決できます。

  1. ファイルを作成するには、checksums.csvファイルパスだけが必要です。

    awk -F'~' '{ system("cksum /opt/xyz"substr($2,8)) }' file.csv > checksums.csv
    

    substr($2,8)プレフィックスを削除しstore://opt/xyz前に追加してパスを完成させます。このsystem(…)コマンドは、指定されたパスでコマンドを実行し、cksum出力を出力ファイルにリダイレクトします。

    サンプル出力は次のとおりです。

    $ cat checksums.csv
    128361894 41 /opt/xyz/2018/7/20/11/35/3f176f4b-41a0-4ac4-a795-a2240ffbb7b9.bin
    820470222 41 /opt/xyz/2018/7/20/11/35/4302b390-1134-424d-a92f-ad27b233e8c1.bin
    1593587341 41 /opt/xyz/2018/7/20/11/35/5ff59679-b3ec-46d2-aa7d-5ec28eff6fe9.bin
    

    出力にはチェックサム、バイト数、パスの3つの列が含まれているため、次のステップで3番目と1番目の列を抽出する必要があります。

  2. ヘッダー行を印刷し、列1(ファイル名)をfile.csv列3(パス)および列1(チェックサム)とマージしますchecksums.csv

    { echo "filename contenturl checksum";\
      paste -d ' ' <(awk -F'~' '{ print $1 }' file.csv) <(awk '{ print $3,$1 }' checksums.csv);\
    } > newfile.csv
    

    出力例:

    $ cat newfile.csv
    filename contenturl checksum
    000224.pdf /opt/xyz/2018/7/20/11/35/3f176f4b-41a0-4ac4-a795-a2240ffbb7b9.bin 128361894
    000238.pdf /opt/xyz/2018/7/20/11/35/4302b390-1134-424d-a92f-ad27b233e8c1.bin 820470222
    000262.pdf /opt/xyz/2018/7/20/11/35/5ff59679-b3ec-46d2-aa7d-5ec28eff6fe9.bin 1593587341
    

    その後、クリーンアップします。

    rm checksums.csv
    

答え2

GNUには、スクリプトのようにシェル処理を統合するためのコマンドフラグがsedあります。escksum

sed -E 'h;s_.*~store:/([^~]*).*_cksum /opt/xyz\1_e;x;G;s_~[^~]*(.*)\n(.*) .* (.*)_~\2~\3\1_;s/~/  /g'
  • -E読みやすくするために拡張正規表現に切り替えるオプション
  • h現在行を予約済みスペースに保存して、必要に応じて処理できます。
  • s_.*~store:/([^~]*).*_cksum /opt/xyz\1_estore:/(削除する)、()再利用するファイル名\1、残りの行(削除する)を含むすべての項目を一致させ、cksum+パスに置き換えます。フラグはeこのコマンドを実行し、パターンスペースを返された内容に置き換え始めます。
  • x;Gホールドスペースとパターンスペースを変更し、パターンスペースにホールドを追加してバッファに次のものを含めます。
  • s_~[^~]*(.*)\n(.*) .* (.*)_~\2~\3\1_読む必要があるかもしれませんが、書き込みが簡単です。~[^~]*2番目のフィールド、(.*)\n元の行の残りの部分、(.*) .* (.*)3つのフィールドが返されるので、cksum2番目のフィールドはファイル名とチェックサムに置き換えられます。
  • 質問に書きませんでしたが、例には~区切り文字はありませんが、2つのスペースがあります。s/~/ /g

関連情報