下面是我想要完成的任务的某种伪代码:
#!/bin/bash
# I already have the variable below figured out (positive integer):
numlines=$([returns number of lines containing specific characters in a file])
# This is basically what I want to do with it:
for i in {1..$numlines}; do
# the part below is already figured out as well:
do some other stuff
done
我可以通过在“{1..n}”序列中插入实际数字来从命令行很好地执行它。我只需要知道是否可以在此处包含变量以及如何去做。
- 我已经尝试过
export
了 - 我尝试将变量本身放在序列内的大括号中:
{1..${numlines}}
- 我尝试将其放在双引号中,希望它能够扩展:
{1.."$numlines"}
- 我尝试过逃避
$
:{1..\$numlines}
我是否需要使用set -[something]
命令才能扩展此变量?我什至尝试过某些形式的使用eval
......但都无济于事。
我只需要知道我是否遗漏了一些简单或晦涩的东西,或者在我浪费时间之前这是否可能。
我可以拼凑出一个真正的、真的这是一种黑客方式,可以使其根据需要工作,但如果可能的话,我想避免这种情况,并学习正确的方法来做到这一点。
答案1
不幸的是,无法在该扩展中使用变量(AFAIK),因为变量扩展发生在大括号扩展之后。
幸运的是,有一个工具可以完成同样的工作。
for i in $(seq 1 $numlines); do
# stuff
done
seq
来自 GNU coreutils;不知道如何在 POSIX 中做到这一点。
答案2
当然。如果您想要一个递增整数变量的 for 循环,请使用以下形式for
环形递增整数变量(或者更一般地对循环变量执行算术)。
for ((i=1; i<=numlines; i++)); do … done
此构造在 bash(以及 ksh93 和 zsh)中有效,但在普通 sh 中无效。在普通 sh 中,使用 while 循环和 test ( [ … ]
) 结构。
i=1
while [ "$i" -le "$numlines" ]; do
…
i=$((i+1))
done
答案3
如果你必须避免seq
,正如汤姆·亨特指出的那样,这似乎是解决这个问题的常用方法,那么eval
绝对是能这样做(不过,我不鼓励这样做):
eval 'for i in {1..'$numlines'}; do echo $i; done'
您可以通过避免 {} 扩展来保持 POSIX,并且只需对 进行数学和整数比较$numlines
:
while [ ! "$numlines" -eq 0 ]; do
echo "$numlines"
: $((numlines-=1))
done
在 POSIX 之外,bash
并且ksh
和zsh
也有 C 风格的for
循环:
for((i=0; i<numlines; i++)); do echo $i; done