私は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 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