在bash for循环中调用当前和下一个项目

时间:2015-05-26 14:53:21

标签: linux bash for-loop

我正在进行重复分析,并且必须向大型计算机集群上的批处理系统提交超过5000个作业。

我想要运行bash for循环但是同时调用当前列表项和我脚本中的下一项。我不确定使用这种格式的最佳方法:

#! /bin/bash
for i in `cat list.txt`; 
do
    # run a bunch of code on $i (ex. Data file for 'Apples')
    # compare input of $i with next in list {$i+1} (ex. Compare 'Apples' to 'Oranges', save output)
    # take output of this comparison and use it as an input for the next analysis of $i (ex. analyze 'Apples' some more, save output for the next step, analyze data on 'Oranges')
    # save this output as the input for next script which analyses the next item in the list {$i+1}  (Analysis of 'Oranges' with input data from 'Apples', and comparing to 'Grapes' in the middle of the loop, etc., etc.)
done

在while循环中提供表格输入列表是否最简单?我真的不想这样做,因为我必须做一些代码编辑,虽然很小。

感谢您帮助一个新手 - 我看了遍遍各种各样的互联网并浏览了一堆书,并没有找到一个很好的方法来做到这一点。

编辑:出于某种原因,我认为可能有一个for循环技巧来做到这一点,但我猜不是;我可能更容易用表格输入做一个while循环。我准备这样做,但我不想重写我已经拥有的代码。

更新:非常感谢您的时间和投入!非常感谢。

4 个答案:

答案 0 :(得分:3)

这个答案假定您希望您的值重叠 - 这意味着在下一次迭代中,next给出的值会变为curr

假设您将代码封装在一个函数中,该函数在下一个项目存在时接受两个参数(当前和下一个),或者在最后一个项目时接受一个参数:

# a "higher-order function"; it takes another function as its argument
# and calls that argument with current/next input pairs.
invokeWithNext() {
  local funcName=$1
  local curr next

  read -r curr
  while read -r next; do
    "$funcName" "$curr" "$next"
    curr=$next
  done
  "$funcName" "$curr"
}

# replace this with your own logic
yourProcess() {
  local curr=$1 next=$2
  if (( $# > 1 )); then
    printf 'Current value is %q, and next item is %q\n' "$curr" "$next"
  else
    printf 'Current value is %q; no next item exists\n' "$curr"
  fi
}

完成这些定义后,您可以运行:

invokeWithNext yourProcess <list.txt

...产量输出如:

Current value is 1, and next item is 2
Current value is 2, and next item is 3
Current value is 3, and next item is 4
Current value is 4, and next item is 5
Current value is 5; no next item exists

答案 1 :(得分:2)

$ printf '%d\n' {0..10} | paste - -
0   1
2   3
4   5
6   7
8   9
10  

所以如果你只是想插入行,这样你就可以每行读取两个变量......

while read -r odd even; do
    …
done < <(paste - - < inputfile)

如果您的行包含空格,则需要执行其他工作。

答案 2 :(得分:2)

另一种解决方案是使用bash数组。例如,给定文件list.txt,其内容为:

1
2
3
4
4
5

您可以使用文件的行创建一个数组变量,其格式为:

$ myarray=(1 2 3 4 4 5)

虽然您也可以执行myarray=( $(echo list.txt) ),但这可能会在空格上分割并且不恰当地处理其他输出,更好的方法是:

$ IFS=$'\n' read -r -d '' -a myarray < list.txt

然后您可以访问元素:

$ echo "${myarray[2]}"
3

数组的长度由${#myarray[@]}给出。所有索引的列表由${!myarray[@]}给出,您可以遍历此索引列表:

for i in "${!myarray[@]}"; do 
    echo "${myarray[$i]} ${myarray[$(( $i + 1))]}" 
done

输出:

1 2
2 3
3 4
4 4
4 5
5

虽然对于您的特定用例可能有更简单的解决方案,但这将允许您在循环中访问数组元素的任意组合。

答案 3 :(得分:1)

我会用while read xx循环替换for循环。

的内容
cat list.txt | while read line; do
  if read nextline; then
     # You have $line and $nextline
  else
     # You have garbage in $nextline and the last line of list.txt in $line
  fi
done