次のCSVがあるとしましょう。
$ cat test.csv
id,domain
1,foo.com
2,bar.com
を使用すると、mlr put
Millerで定義できる限り、すべての機能をCSVのフィールドに簡単にマッピングできます。DSL。たとえば、mlr --csv put '$id = $id + 1'
レコードごとに 1 ずつ増加します。id
しかし、Miller DSLで関数を定義できない場合(おそらく純粋な関数ではないので)どうなりますか? CSVの各ドメインをIPアドレスにマッピングするとします。私は似たようなことをしたいですmlr --csv put '$ip = shell("nslookup $domain")
。見つけることができるショートカットがありますか?
現在の入力フィールドを別々のファイルに抽出し、それを別のシェルスクリプトとして再構築してから、結果を再度追加していますmlr join
。しかし、私のCSVは引用符、カンマ、および改行でいっぱいですので、これは非常に混乱しています。 Millerに頼るのではなく、慎重に処理する必要があります。
答え1
修正する: 2019年9月現在、これ
system()
DSL機能この目的に使用できます。
Miller DSLで外部コマンドを呼び出す
外部コマンド呼び出しのためのMiller DSLリファレンスセクションリダイレクト出力ステートメント:
これ印刷、ダンプ、ティー、排出量、放射と放射両方のキーワードを使用すると、出力を1つ以上のファイルにリダイレクトできます。またはパイプコマンド。
ドキュメントにこれが見つかりませんが(例から推論することを除く)、パイプライン-toコマンドでこれらのステートメントを使用する構文は次のとおりです{statement} | {quoted-shell-command}, {unquoted-mlr-expression}
。
$ mlr --csv put 'tee | "tr [a-z] [A-Z]", $*' test.csv
id,domain
1,foo.com
2,bar.com
ID,DOMAIN
1,FOO.COM
2,BAR.COM
パイプ出力は、Millerの出力(この場合、ストリームはtee
影響を受けずに放出されないため、put
変更されていない入力)の後に表示されます。抑制された出力を使用しput
て個々のフィールドを抽出する代わりに、-q
IPアドレスのリストを取得できます。print $domain
tee $*
$ mlr --csv put -q 'print | "xargs dig +short", $domain' test.csv
23.23.86.44
104.27.138.186
104.27.139.186
Millerはここで私たちのために多くのことをしません。xargs
標準入力を引数に変換する必要があります(dig
標準入力のフィールドは許可されていないため)。また、dig
の出力には改行文字が含まれています。これは、出力が入力と一対一で一致しなくなったことを意味します。 Unixの哲学によると、それが私が必要とするものであれば、mlr
最後までパイプするのが簡単になります。mlr --headerless-csv-output cut -f domain
外部コマンドの出力を入力に接続
私が本当に望むのは、Miller DSLの内部ストリーム変数に外部コマンドを呼び出した結果を割り当てることです。、私が知る限り、これは不可能です。しかし、xargs
交換を通じて牛に似た一種の栄養parallel
、この--tag
オプションを使用して提供する引数を追跡し、dig
柔軟な同時I / Oの利点を享受できます。
$ mlr --csv --headerless-csv-output cut -f domain test.csv | parallel --tag dig +short
foo.com 23.23.86.44
bar.com 104.27.139.186
bar.com 104.27.138.186
CSVを扱っているので、名前()ではなくparallel
場所()でフィールドにアクセスする必要がありますが、実際には直接処理できます。{2}
domain
$ < test.csv parallel -C "," --skip-first-line --tagstring {2} dig +short {2}
foo.com 23.23.86.44
bar.com 104.27.139.186
bar.com 104.27.138.186
これはタブで区切られたペアのリストなので、(domain, ip)
.txtを使用してヘッダー付きのCSVに戻すことができますmlr --t2c --implicit-csv-header label domain,ip
。その後、出力データとソースデータtest.csv
の両方にフィールドがあるため、これを使用して複数の値を含む単一の出力テーブルを作成domain
できます。mlr join
mlr nest
bar.com
$ mlr --csv cut -f domain test.csv | \
parallel --skip-first-line --tag dig +short | \
mlr --t2c --implicit-csv-header label domain,ip | \
mlr --c2p --barred join -f test.csv -j domain then \
nest --implode --values --across-records -f ip
+---------+----+-------------------------------+
| domain | id | ip |
+---------+----+-------------------------------+
| foo.com | 1 | 23.23.86.44 |
| bar.com | 2 | 104.27.138.186;104.27.139.186 |
+---------+----+-------------------------------+