2つの入力ファイルを繰り返す方法

2つの入力ファイルを繰り返す方法

私はawkを使って2つのファイルを一致させ、次にfile2とfile1の要素を掛けます。

 awk 'NR == FNR{a[$1]=$2; b[$1]=$3; next}
      /:/ || !NF{print; next}
     {print $1, $2*a[$1], $2*b[$1]}' file2 file1 > output

スクリプトは2つの入力ファイルのみを処理し、1つの出力ファイルを生成します。

私はこのスクリプトを多くの(何千もの)ファイルで使用するためにループを作りたいと思います。私はこれを試みます:

for file1 in ../mo/*e.log | 
for file2 in ../excited/*-d.log;   do
awk 'NR == FNR{a[$1]=$2; b[$1]=$3; next}
     /:/ || !NF{print; next}
     {print $1, $2*a[$1], $2*b[$1]}' "$file1" "$file2" > "${file1%e.log}f.log"
done

ファイルは互いに関連しているため、0001e.logと0001-d.log、0002e.log、0002-d.log、0002e.log、0002-d.log ...予想される出力は0001f.log、0002fです。 。 .log、0003f。ログ...

しかし、成功しませんでした。どんなアイデアがありますか?

答え1

おそらくあなたは以下が欲しいでしょう:

set ../mo/*e.log
for file2 in ../excited/*-d.log; do
  file1=$1; shift
  awk 'NR == FNR{a[$1]=$2; b[$1]=$3; next}
       /:/ || !NF{print; next}
       {print $1, $2*a[$1], $2*b[$1]}' "$file1" "$file2" > "${file1%e.log}f.log"
done

または以下を使用してzsh

file1s=(../mo/*e.log)
file2s=(../excited/*-d.log)
for file1 file2 (${file1s:^file2s}) {
  awk 'NR == FNR{a[$1]=$2; b[$1]=$3; next}
       /:/ || !NF{print; next}
       {print $1, $2*a[$1], $2*b[$1]}' "$file1" "$file2" > "${file1%e.log}f.log"
}

上記では、2つのソートされたファイル名のリストがあり、両方のリストを同時に移動します。 inファイルとinファイルのデフォルト名を一致させるには、mo次のようにします。excited

for file1 in ../mo/*e.log; do
  basename=${file1%e.log}
  basename=${basename##*/}
  file2=../excited/$basename-d.log
  [ -f "$file2" ] || continue
  awk 'NR == FNR{a[$1]=$2; b[$1]=$3; next}
       /:/ || !NF{print; next}
       {print $1, $2*a[$1], $2*b[$1]}' "$file1" "$file2" > "${file1%e.log}f.log"
done

答え2

努力するpaste file1 file2 | tr '\t' '*' | bc > output

その後、大きなループの場合(強く打つ)、これはファイルを次から変更します。../月/../興奮/、そして製品を次に出力します。F現在のディレクトリにある一連の番号付きファイル:

for f in ../mo/*e.log; do
    g=${f/mo/excited}
    o=${f##*/}
    paste $f ${g/e.log/-d.log} | tr '\t' '*' | bc > ${o/e.log/f.log} 
done

デモ(強く打つisms)、1〜5の2乗を印刷します。

paste <(seq 5) <(seq 5) | tr '\t' '*' | bc

出力:

1
4
9
16
25

答え3

GNU Parallelがインストールされている場合は、次のことができます。

doit() {
  file1="$1"
  file2="$2"
  output="$3"
  awk 'NR == FNR{a[$1]=$2; b[$1]=$3; next}
      /:/ || !NF{print; next}
     {print $1, $2*a[$1], $2*b[$1]}' "$file2" "$file1" > "$output"
}
export -f doit

# If all filenames fit on a command line:
parallel --xapply doit {1} {2} {1/.}{2/.}.out ::: ../mo/?*e.log ::: ../excited/?*d.log
# With newer versions you can do:
parallel  doit {1} {2} {1/.}{2/.}.out ::: ../mo/?*e.log :::+ ../excited/?*d.log

# If you do not like the {/.} you can do:
parallel doit {1} '{= s/e.log/d.log/;s:/mo/:/excited/:; =}' '{=s/.log/.out/;s:^../mo/::;=}' ::: ../mo/?*e.log

# If all the files do not fit on the command line (because you have thousands):
finda() { find ../mo/ -name '*e.log'; }
findb() { find ../excited/ -name '*d.log'; }

parallel --xapply doit {1} {2} {1/.}{2/.}.out :::: <(finda) <(findb)
parallel doit {1} {2} {1/.}{2/.}.out :::: <(finda) ::::+ <(findb)
finda | parallel doit {1} '{= s/e.log/d.log/;s:/mo/:/excited/:; =}' '{=s/.log/.out/;s:^../mo/::;=}'

各コアは1つのタスクを実行します。一度に1つの操作を実行するには、parallelに置き換えますparallel -j1

GNU Parallelは、同じコンピュータまたはSSHを介してアクセスできる複数のコンピュータでタスクを並列に簡単に実行できる汎用の並列ハンドラです。多くの場合for、ループを置き換えることができます。

4つのCPUで32の異なるジョブを実行する場合は、並列化する簡単な方法は、各CPUで8つのジョブを実行することです。

簡単なスケジューリング

代わりに、GNU Parallel はタスクが完了すると新しいプロセスを作成し、CPU をアクティブに保つことで時間を節約します。

GNU並列スケジューリング

インストールする

ディストリビューションにGNU Parallelがパッケージされていない場合は、rootアクセスなしでプライベートインストールを実行できます。これは10秒で完了できます。

(wget -O - pi.dk/3 || curl pi.dk/3/ || fetch -o - http://pi.dk/3) | bash

その他のインストールオプションについては、以下を参照してください。http://git.savannah.gnu.org/cgit/parallel.git/tree/README

詳細

より多くの例を見る:http://www.gnu.org/software/parallel/man.html

紹介ビデオを見る:https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1

このチュートリアルを見てください。http://www.gnu.org/software/parallel/parallel_tutorial.html

サポートを受けるには、メールリストに参加してください。https://lists.gnu.org/mailman/listinfo/parallel

関連情報