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


10

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

#!/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...全部无济于事。

我只需要知道我是否缺少一些简单或晦涩的东西,或者甚至在我再浪费时间之前就可以做到。

为了使它按需运行,我可能会提出一种非常真正的方法,但是我想尽可能避免这种情况,并学习正确的方法。


Answers:


11

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

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

for i in $(seq 1 $numlines); do
    # stuff
done

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


1
(加号1)。 seq对GNU系统和(如果我没记错的话)最新的OSX是好的。在其他BSD系统上,可以使用jot代替。
John1024

seq完美地工作。非常感谢您的迅速回答。
rubynorails

这不是我的问题的一部分-但是以相反的顺序执行语法是什么(如果有的话),例如{16..1}$(seq $numlines 1)不工作。我想我永远可以man seq,但是想知道是否有人知道他们的头脑。
rubynorails

1
只是想出了如何做到这一点的反向从这个链接 -for i in $(seq $numlines -1 1)
rubynorails

seq ${numlines} -1 0
DopeGhoti 2015年

10

当然。如果要使整数变量递增的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

8

如果您必须避免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之外,bashkshzsh也有C风格for的循环:

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

1
我也非常感谢这个答案。虽然seq在我的情况下可以正常工作,并且似乎是最简单的解决方案,但很高兴知道还有其他(甚至是POSIX)替代方案。谢谢你
rubynorails

2
确实没有理由使用eval;如果您有大括号扩展,您将拥有C样式的循环。
chepner

@PSkocik-如果我可以选择2个答案,我也会选择这个答案。当我遇到需要反向进行操作的事实时,您的eval示例是最简单的示例,它将使我免于不得不使用来寻找替代方法的麻烦seq。该while循环对我来说是有点笨重。我喜欢使事情简短明了,并且我永远无法for通过给出i0或1的值来使C风格的循环正常工作。我确信可以对其进行调整以使其正常工作,但是尽管如此,这些绝对是有用的解决方案。
rubynorails

eval如果循环体内有任何不平凡的东西,这种方法就会有问题。我想如果您需要嵌套两个这样的循环,它就不会很可读。
kasperd 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.