我可以在 Bash 大括号扩展中使用变量吗?

我可以在 Bash 大括号扩展中使用变量吗?

下面是我想要完成的任务的某种伪代码:

#!/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并且kshzsh也有 C 风格的for循环:

for((i=0; i<numlines; i++)); do echo $i; done

相关内容