我正在进行重复分析,并且必须向大型计算机集群上的批处理系统提交超过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循环。我准备这样做,但我不想重写我已经拥有的代码。更新:非常感谢您的时间和投入!非常感谢。
答案 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