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

rub*_*ils 12 scripting bash shell-script

以下是我要完成的某种伪代码:

#!/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
Run Code Online (Sandbox Code Playgroud)

通过在“{1..n}”序列中插入实际数字,我可以从命令行很好地执行它。我只需要知道是否可以在这里包含一个变量以及如何去做。

  • 我试过export
  • 我尝试将变量本身放在序列内的花括号中: {1..${numlines}}
  • 我试过把它放在双引号中,希望它能扩展: {1.."$numlines"}
  • 我试过逃避${1..\$numlines}

我是否需要使用set -[something]命令才能扩展此变量?我什至尝试过某些形式的使用eval...都无济于事。

我只需要知道我是否遗漏了一些简单或晦涩的东西,或者在我浪费时间之前这是否可能。

我可以拼凑出一种非常非常hackish 的方式来让它根据需要工作,但如果可能的话,我想避免这种情况,并学习正确的方法来做这件事。

Tom*_*unt 12

不幸的是,无法在该扩展(AFAIK)中使用变量,因为变量扩展发生在大括号扩展之后。

幸运的是,有一个工具可以完成同样的工作。

for i in $(seq 1 $numlines); do
    # stuff
done
Run Code Online (Sandbox Code Playgroud)

seq来自 GNU coreutils;不知道如何在 POSIX 中做到这一点。


PSk*_*cik 10

如果您必须避免seq,正如汤姆亨特指出的那样,这似乎是解决此问题的常用方法,那么eval绝对可以做到(不过,我不鼓励这样做):

eval 'for i in {1..'$numlines'}; do echo $i; done'
Run Code Online (Sandbox Code Playgroud)

您可以通过避免 {} 扩展来保持 POSIX,只需对 进行数学和整数比较$numlines

while [ ! "$numlines" -eq 0 ]; do
     echo "$numlines"
     : $((numlines-=1))
done
Run Code Online (Sandbox Code Playgroud)

POSIX之外,bashkshzsh也有C风格for的循环:

for((i=0; i<numlines; i++)); do echo $i; done
Run Code Online (Sandbox Code Playgroud)

  • 真的没有理由使用 `eval`;如果你有大括号扩展,你就有了 C 风格的循环。 (2认同)

Gil*_*il' 10

当然。如果您想要一个递增整数变量的 for 循环,请使用递增整数变量的for循环形式(或更一般地对循环变量执行算术运算)。

for ((i=1; i<=numlines; i++)); do … done
Run Code Online (Sandbox Code Playgroud)

此构造适用于 bash(以及 ksh93 和 zsh),但不适用于普通 sh。在普通 sh 中,使用 while 循环和 test ( [ … ]) 构造。

i=1
while [ "$i" -le "$numlines" ]; do
  …
  i=$((i+1))
done
Run Code Online (Sandbox Code Playgroud)