web-dev-qa-db-ja.com

個別の行を、引用符で囲まれたエントリを含むコンマ区切りのリストに変える

次のデータ(Rmarkdownファイルから解析されたRパッケージのリスト)があり、それを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_フラグを削除)は、入力と同じ出力を生成します。

15
fbt

sedを使用して引用符を追加し、次にpasteを使用して行をマージできます。

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

GNU coreutilsベースのシステム(つまりLinux))を実行している場合は、末尾の'-'を省略できます。

入力データにDOSスタイルの行末がある場合(@phkが示唆するとおり)、コマンドを次のように変更できます。

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

@ don_crisstiのリンクされた回答 が示すように、貼り付けオプションの境界は信じられないほど高速です-Linuxカーネルのパイプは、今試していない場合に信じていたよりも効率的です。驚くことに、コンマ+スペースではなく、リスト項目を1つのコンマで区切って満足できる場合は、貼り付けパイプライン

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

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

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

しかし、まともなパフォーマンスが許容できる場合(そして、ストレステストを実行していない場合、定数係数の差を測定することはできません。それらはすべて瞬時に行われます)、セパレーターの柔軟性と妥当なセパレーターの両方が必要です。 -liner-y-ness、

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

チケットです。はい、それはラインノイズのように見えますが、H;1h;$!d;xイディオムはすべてをSlurpする正しい方法です。全体が実際に読みやすくなると認識できたら、s/.*/'&'/の後にSlurpと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倍速くなります。

6
jthill

Perl

Pythonワンライナー:

_$ 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()でリストに各行を読み込み、各行。次に、.join()関数を介してリストを1つの大きな文字列に結合し、_,_を区切り文字として使用します

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

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

Perl

基本的に前と同じアイデア:すべての行を読み取り、末尾の改行を取り除き、一重引用符で囲み、すべてを配列@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'

4

あなたがデータがファイルテキストにあると仮定すると、以下はうまくいくはずです

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

代替のコールド配列を使用してみましょう:

#!/bin/bash
input=( $(cat text) ) 
output=( $(
for i in ${input[@]}
        do
        echo -ne "'$i',"
done
) )
output=${output:0:-1}
echo ${output//,/, }

スクリプトの出力は次のようになります。

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

これはあなたが探していたものだと思いますか?

私はよく似たシナリオをよく持っています。Excelから列をコピーし、コンテンツをコンマ区切りのリストに変換したい(... WHERE col_name IN <comma-separated-list-here>のようなSQLクエリで後で使用するため)。

これは私の.bashrcにあるものです:

function lbl {
    TMPFILE=$(mktemp)
    cat $1 > $TMPFILE
    dos2unix $TMPFILE
    (echo "("; cat $TMPFILE; echo ")") | tr '\n' ',' | sed -e 's/(,/(/' -e 's/,)/)/' -e 's/),/)/'
    rm $TMPFILE
}

次に、入力を待つcmd行でlbl( "行ごと")を実行し、クリップボードからコンテンツを貼り付け、<C-D>を押すと、()で囲まれた入力が関数から返されます。これは次のようになります。

$ lbl
1
2
3
dos2unix: converting file /tmp/tmp.OGM6UahLTE to Unix format ...
(1,2,3)

(なぜ私がdos2unixをここに置いたのか覚えていません。これが会社のセットアップで問題を引き起こすことが多いためです。)

2
Rolf

Rパッケージのプレーンテキストリストを使用してそれらをRにインストールするのはおかしいですが、Rに直接そのリストを使用するソリューションを提案した人はいません。リスト。これはまったく必要ありません。さらに、Rで変換されたリストをどのように入力して使用するかを解決しません。

単純なテキストファイル(つまり、packages.txt)を単一の変数を持つデータフレームとしてロードするだけで、install.packagesで直接使用できるベクターとして抽出できます。したがって、それを使用可能なRオブジェクトに変換し、そのリストをインストールするだけです。

df <- read.delim("packages.txt", header=F, strip.white=T, stringsAsFactors=F)
install.packages(df$V1)

または外部ファイルなし:

packages <-" 
d3heatmap
data.table
ggplot2
htmltools
htmlwidgets
metricsgraphics
networkD3
plotly
reshape2
scales
stringr
"
df <- read.delim(textConnection(packages), 
header=F, strip.white=T, stringsAsFactors=F)
install.packages(df$V1)
1
Fran

Sedの一部のバージョンでは動作が少し異なりますが、私のMacでは、sedの「uniq」以外のすべてを処理できます。

sed -n -e '
# Skip commented library lines
/#/b
# Handle library lines
/library(/{
    # Replace line with just quoted filename and comma
    # Extra quoting is due to command-line use of a quote
    s/library(\([^)]*\))/'\''\1'\'', /
    # Exchange with hold, append new entry, remove the new-line
    x; G; s/\n//
    ${
        # If last line, remove trailing comma, print, quit
        s/, $//; p; b
    }
    # Save into hold
    x
}
${
    # Last line not library
    # Exchange with hold, remove trailing comma, print
    x; s/, $//; p
}
'

残念ながらユニークな部分を修正するには、次のようにする必要があります。

grep library Presentation.md | sort -u | sed -n -e '...'

-ポール

1
PaulC