別の行を引用符で囲まれた項目を含むカンマ区切りリストに変換

別の行を引用符で囲まれた項目を含むカンマ区切りリストに変換

インストールのためにRに渡すことができるリストに変換したいデータ(Rmarkdownファイルから解析されたRパッケージのリスト)があります。

d3heatmap
data.table
ggplot2
htmltools
htmlwidgets
metricsgraphics
networkD3
plotly
reshape2
scales
stringr

リストを次の形式のリストに置き換えたいと思います。

'd3heatmap', 'data.table', 'ggplot2', 'htmltools', 'htmlwidgets', 'metricsgraphics', 'networkD3', 'plotly', 'reshape2', 'scales', 'stringr'

現在、ソースファイルから上記のリストまでのbashパイプラインがあります。

grep 'library(' Presentation.Rmd \
| grep -v '#' \
| cut -f2 -d\( \
| tr -d ')'  \
| sort | uniq

新しい行をカンマ区切りリストに変換する手順を追加したいと思います。追加しようとしましたがtr '\n' '","'失敗しました。また、次のスタックオーバーフローの答えのいくつかを試しましたが、失敗しました。

これは結果をもたらしましたlibrary(stringr)))phics)

これは結果をもたらしました,%

この答え(-iフラグの削除)は入力と同じ出力を生成します。

答え1

引用符を追加できます。sed次に、行を次と比較します。生地、そう:

sed 's/^\|$/"/g'|paste -sd, -

GNU coreutilsベースのシステム(Linuxなど)を実行している場合は末尾'-'

入力したデータにDOSスタイルの行末(@ phk提案)がある場合は、次のようにコマンドを変更できます。

sed 's/\r//;s/^\|$/"/g'|paste -sd, -

答え2

使用awk:
awk 'BEGIN { ORS="" } { print p"'"'"'"$0"'"'"'"; p=", " } END { print "\n" }' /path/to/list
シェルエスケープが少なく、読みやすさの高い代替案:
awk 'BEGIN { ORS="" } { print p"\047"$0"\047"; p=", " } END { print "\n" }' /path/to/list
出力:
'd3heatmap', 'data.table', 'ggplot2', 'htmltools', 'htmlwidgets', 'metricsgraphics', 'networkD3', 'plotly', 'reshape2', 'scales', 'stringr'
説明する:

awkスクリプト自体にはエスケープはまったくありませんBEGIN { ORS="" } { print p"'"$0"'"; p=", " } END { print "\n" }。最初の項目を印刷すると、変数がp設定されます(以前は空の文字列と同じです)。p各項目に対してこの変数を使用するか、awk-speakを使用してください。記録)は接頭辞であり、そうでなければ一重引用符で印刷されます。レコード区切り変数を出力する必要はありません(プレフィックスはすでにこれを実行するため)。 ingの場合はこれを空白に設定してくださいawk。ああ、ファイルに改行文字を追加できます(たとえば、他のテキスト処理ツールと連携するように)。必要でない場合は、後ろの部分とその後のすべての項目を削除できます(一重引用符内)。ORSBEGINENDEND

ノート

Windows / DOSスタイルの行末()がある場合は、\r\nまずUNIXスタイル()に変換する必要があります\n。これを行うには、tr -d '\015'パイプラインの先頭に次を含めることができます。

tr -d '\015' < /path/to/input.list | awk […] > /path/to/output

\r(ファイルにsをまったく使用しないとします。ここではかなり安全な仮定です。)

または、dos2unix /path/to/input.list一度だけ実行してファイルを内部で変換します。

答え3

〜のように@don_crisstiのリンクされた回答貼り付けオプションが非常に高速であることを示しています。 Linuxカーネルのパイプラインは、私が今まで試してきたものよりも効率的です。カンマ + 空白以外のリスト項目を区切る単一のカンマに満足する場合は、パイプを貼り付けます。

(paste -d\' /dev/null - /dev/null | paste -sd, -) <input

合理的なプログラムよりも速いflex(!)

%option 8bit main fast
%%
.*  { printf("'%s'",yytext); }
\n/(.|\n) { printf(", "); }

しかし、まともなパフォーマンスが許容され(ストレステストを実行しないと定数要素の差を測定することはできず、すべて瞬間的に)、スプリッタは柔軟で合理的に線形であることを望みます。

sed "s/.*/'&'/;H;1h;"'$!d;x;s/\n/, /g'

それはあなたの投票です。はい、ラインノイズのように見えますが、このイディオムはすべてを吸収H;1h;$!d;xする正しい方法です。s/.*/'&'/s/\n/, /g


編集:面白いことですが、フレックスを他のものよりも先に進めるのはとても簡単です。組み込みマルチスレッド/信号ハンドラの同期は不要であることをstdioに教えてください。

%option 8bit main fast
%%
.+  { putchar_unlocked('\'');
      fwrite_unlocked(yytext,yyleng,1,stdout);
      putchar_unlocked('\''); }
\n/(.|\n) { fwrite_unlocked(", ",2,1,stdout); }

圧力を加えると、スティックパイプより2〜3倍速く、スティック自体は他のパイプより少なくとも5倍速くなります。

答え4

Python

Python 1行:

$ python -c "import sys; print(','.join([repr(l.strip()) for l in sys.stdin]))" < input.txt                               
'd3heatmap','data.table','ggplot2','htmltools','htmlwidgets','metricsgraphics','networkD3','plotly','reshape2','scales','stringr'

仕組みは簡単です。シェルの<演算子を使用してinput.txtをstdinにリダイレクトし、各行をリストに読み込み、改行を.strip()削除し、各行repr()に引用符付き表現を作成します。次に、関数を使用してリストを1つの大きな文字列に連結し、区切り文字を使用します.join(),

または、削除された各行に引用符を連結して使用することもできます+

 python -c "import sys;sq='\'';print(','.join([sq+l.strip()+sq for l in sys.stdin]))" < input.txt

真珠

本質的に以前と同じアイデアです。すべての行を読み、次の改行を削除し、一重引用符で囲み、すべてを@cvs配列に埋め込み、コンマで連結された配列値を印刷します。

$ perl -ne 'chomp; $sq = "\047" ; push @cvs,"$sq$_$sq";END{ print join(",",@cvs)   }'  input.txt                        
 'd3heatmap','data.table','ggplot2','htmltools','htmlwidgets','metricsgraphics','networkD3','plotly','reshape2','scales','stringr'

関連情報