循环在bash中的值对

我有10个文本文件,我想paste每对文件,使我有5个文件。

我尝试了以下内容:

 for i in 4_1 5_1 6_1 7_1 8_1 do for j in 4_2 5_2 6_2 7_2 8_2 do paste ${i}.txt ${j}.txt > ${i}.${j}.txt done done 

但是,这个代码结合了所有可能的组合,而不是仅仅组合匹配对。

所以我想要文件4_1.txt4_2.txt配对, 5_1.txt5_2.txt等配对

如果你想使用一个variables,并执行和动作,你只需要使用一个循环:

 for file in 4 5 6 7 8 do paste "${file}_1" "${file}_2" done 

这会做

 paste 4_1 4_2 paste 5_1 5_2 ... 

我同意在目前提出的问题的背景下,目前由fedorqui提出的答复。 下面只给出一些更一般的答案。

一个更为普遍的方法(对于bash 4.0或更新)是将你的对存储在一个关联数组中:

 declare -A pairs=( [4_1]=4_2 [5_1]=5_2 [6_1]=6_2 [7_1]=7_2 [8_1]=8_2 ) for i in "${!pairs[@]}"; do j=${pairs[$i]} paste "$i.txt" "$j.txt" >"${i}.${j}.txt" done 

另一个(兼容bash的旧版本)是使用多个常规数组:

 is=( 4_1 5_1 6_1 7_1 8_1 ) js=( 4_2 5_2 6_2 7_2 8_2 ) for idx in "${!is[@]}"; do i=${is[$idx]} j=${js[$idx]} paste "$i.txt" "$j.txt" >"$i.$j.txt" done 

有一个共同的模式,你有一对文件,其中的一个名称可以很容易地从另一个派生。 如果你知道这个文件的名字是X而另一个文件是Y的话,你有以下的常见用例。

  • 对于重命名,Y是X,删除了扩展名和/或添加了date标记。
  • 对于转码,Y是X,具有不同的扩展名,也许是不同的目录。
  • 对于许多数据分析任务,X和Y共享文件名的某些部分,但具有不同的参数或扩展名。

所有这些都适用于相同的粗略代码框架。

 for x in path/to/base*.ext; do dir=${x%/*} # Trim trailing file name, keep dir base=${x##*/} # Trim any leading directory # In this case, $y has a different subdirectory and a different extension y=${dir%/to}/from/${base%.ext}.newext # Maybe check if y exists? Or doesn't exist? if [ -e "$y" ]; then echo "$0: $y already exists -- skipping" >&2 continue fi mv or ffmpeg or awk or whatever "$x" and "$y" done 

这里的关键是观察y可以通过一些简单的variablesreplace从x推导出来。 所以你循环x值,并找出循环内的相应的y值。

在这里,我们使用了shell的内置${variable#prefix}${variable%suffix}运算符来分别返回variables的值, prefix或尾部suffix修剪掉了。 (也有##%%匹配最长的,而不是最短的可能的匹配。 #%之后的expression式是一个普通的shell glob模式。)这些应该通常是你所需要的,尽pipe你经常看到sedawk脚本,甚至对于这个微不足道的工作(你通常应该尽量避免一个外部的过程),当然还有更多的转换。

如果你需要循环遍历不同目录的x文件,也许循环应该从类似的东西开始

  find dir1 dir2 etc/and/so/forth -type f -name 'x-files*.ext' -print | while IFS='' read -rx; do : 

类似问题中常见的问题是没有正确引用$x$y答案。 通常,任何包含文件名的variables都应该使用双引号。

在X和Y不相关的情况下,常见的解决scheme是循环包含映射的here文档:

 while read -rxy; do : stuff with "$x" and "$y" done <<'____HERE' first_x_value first_y_value another_x corresponding_y random surprise ____HERE