我使用 awk 来匹配两个文件,然后将 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
该脚本仅处理两个输入文件并生成一个输出文件。
我想做一个循环来将此脚本用于许多(数千个)文件。我尝试这样做:
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.log ...
但没有成功。有任何想法吗?
答案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"
}
上面,我们有两个排序的文件名列表,并且我们并行地浏览这两个列表。如果要匹配inmo
和 in文件的基本名称,您可以这样做: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 的平方:
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/::;=}'
每个核心将运行一项作业。如果您更喜欢一次只做一项工作,请替换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