我有几个文件(表),命名为:研究所_
模型_
设想_
河.txt
(研究所,模型,设想, 和河是变量。)我想创建一个for
循环来识别具有相同研究所名称,同时相同设想名称,以便附加每个不同的结果模型在同一个输出文件中,使用以下命令:
paste filename1.txt filename2.txt > output_file.txt
我知道如何创建for
不同文件夹的循环,但不知道如何创建文件名的循环。有人有想法吗?
作为一个最小的例子,文件名可以如下:
wbm_gfdl_rcp8p5_mississippi.txt
wbm_hadgem_rcp8p5_mississippi.txt
matsiro_gfdl_rcp8p5_mississippi.txt
matsiro_ipsl_rcp4p5_mississippi.txt
matsiro_hadgem_rcp4p5_mississippi.txt
matsiro_miroc_rcp8p5_mississippi.txt
然后,我想将以下文件附加在一起:
wbm_gfdl_rcp8p5_mississippi.txt with
wbm_hadgem_rcp8p5_mississippi.txt
matsiro_ipsl_rcp4p5_mississippi.txt with
matsiro_hadgem_rcp4p5_mississippi.txt
matsiro_gfdl_rcp8p5_mississippi.txt with
matsiro_miroc_rcp8p5_mississippi.txt
答案1
首先,for
目录循环和文件循环没有区别。它们完全一样。请记住,在 *nix 上,一切皆文件。
因此,你的循环将是这样的:
for institute in institute1 institute2 institute3
do
for scenario in scenario1 scenario2 scenario3
do
paste "$institute"_*_"$scenario"* > "$institute"_"$scenario".out
done
done
如果您不知道机构和场景名称,您可以对所有文件运行此操作并从文件名中提取它们(只要您的名称不包含空格):
for f in *; do echo "${f/_*} ${f##*_}"; done |
sort -u | while read ins sce; do
paste "$ins"_*_"$sce"* > "$ins"_"$sce".out
done
答案2
如果文件都在同一个目录中,您可以:
ls |
awk -F_ '{ i=$1; m=$2; s=$3; f[i"_"s] = f[i"_"s] " " $0 }
END{ for(insc in f)
printf "paste%s >out_%s.txt\n",f[insc],insc
}'
它将文件名拆分为“_”(-F_
),将变量 i、m、s 设置为文件名的前 3 个部分(研究所、模型、场景),并在数组 f 中累积文件名。该数组仅由研究所和场景索引,因此所有模型都连接在一起(不使用 m)。最后的 END 打印 f 数组,并使用索引(研究所_场景)作为输出文件的名称。使用您的示例,这将产生
paste wbm_gfdl_rcp8p5_mississippi.txt wbm_hadgem_rcp8p5_mississippi.txt >out_wbm_rcp8p5.txt
paste matsiro_hadgem_rcp4p5_mississippi.txt matsiro_ipsl_rcp4p5_mississippi.txt >out_matsiro_rcp4p5.txt
paste matsiro_gfdl_rcp8p5_mississippi.txt matsiro_miroc_rcp8p5_mississippi.txt >out_matsiro_rcp8p5.txt
然后您需要将其导入到 shell 中以执行它。添加| sh
到上面的最后一行即可执行此操作。
要从输入文件中删除某些列,您需要修改收集所有输入文件名的 awk 行。在第一行 awk 中:
{ i=$1; m=$2; s=$3; f[i"_"s] = f[i"_"s] " " $0 }
文件名是“$0”。例如,如果你将此行更改为:
{ i=$1; m=$2; s=$3; f[i"_"s] = f[i"_"s] sprintf(" <(cut -f4 %s)",$0) }
然后您将获得示例输出:
paste <(cut -f4 wbm_gfdl_rcp8p5_mississippi.txt) <(cut -f4 wbm_hadgem_rcp8p5_mississippi.txt) >out_wbm_rcp8p5.txt
但如果您只想剪切第二个文件名,那就有点复杂了,您需要这样做:
{ i=$1; m=$2; s=$3;
if(f[i"_"s]=="")add = $0; else add = sprintf("<(cut -f4 %s)",$0);
f[i"_"s] = f[i"_"s] " " add }
所以你会得到
paste wbm_gfdl_rcp8p5_mississippi.txt <(cut -f4 wbm_hadgem_rcp8p5_mississippi.txt) >out_wbm_rcp8p5.txt
如果sh
不明白语法<(cut ...)
则用 替换它bash
。
答案3
也许可以使用 ls 命令。类似的东西ls $institute_*_$scenario_*.txt
应该返回具有相同机构和场景的所有文件。