Miller DSLで外部コマンドを呼び出す

Miller DSLで外部コマンドを呼び出す

次のCSVがあるとしましょう。

$ cat test.csv
id,domain
1,foo.com
2,bar.com

を使用すると、mlr putMillerで定義できる限り、すべての機能を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て個々のフィールドを抽出する代わりに、-qIPアドレスのリストを取得できます。print $domaintee $*

$ 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 joinmlr nestbar.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 |
+---------+----+-------------------------------+

おすすめ記事