Bash循环,打印当前迭代?

20 bash loops while-loop

假设你有一个简单的循环

while read line
do
  printf "${line#*//}\n"
done < text.txt
Run Code Online (Sandbox Code Playgroud)

是否有一种优雅的方式来打印输出的当前迭代?就像是

0 The
1 quick
2 brown
3 fox

我希望避免设置变量并在每个循环上递增它.

jor*_*anm 29

要做到这一点,你需要在每次迭代时增加一个计数器(就像你试图避免的那样).

count=0
while read -r line; do
   printf '%d %s\n' "$count" "${line*//}"
   (( count++ ))
done < test.txt
Run Code Online (Sandbox Code Playgroud)

编辑:经过一番思考,如果你有bash版本4或更高版本,你可以在没有计数器的情况下完成:

mapfile -t arr < test.txt
for i in "${!arr[@]}"; do
   printf '%d %s' "$i" "${arr[i]}"
done
Run Code Online (Sandbox Code Playgroud)

mapfile内置文件将文件的全部内容读入数组.然后,您可以迭代数组的索引,这将是行号并访问该元素.

  • 很好的解决方案,虽然如果你处理大文件,`mapfile`可能会非常耗费内存.在不知道OP的文件大小的情况下,我建议使用通过管道传输的东西,因此文件大小也是不可知的. (3认同)

Pau*_*ce. 14

您不经常看到它,但是您可以在while循环的condition子句中拥有多个命令.以下仍然需要明确的计数器变量,但是对于某些用途,该布置可能更合适或更吸引人.

while ((i++)); read -r line
do
    echo "$i $line"
done < inputfile
Run Code Online (Sandbox Code Playgroud)

while条件是什么最后的命令返回(满足read在这种情况下).

有些人喜欢把它们do放在同一条线上.这就是这样:

while ((i++)); read -r line; do
    echo "$i $line"
done < inputfile
Run Code Online (Sandbox Code Playgroud)

  • @jordanm:`for`做了类似的事情:`for((i = 0,j = 14; i <= 20; i ++,j + = 11))`.此外,您可以一次从文件中读取两行(或更多行):`read read -r oddline; 读-r偶数线; 回声"奇怪:[$ oddline]甚至:[$ evenline]"; 完成<filename` (5认同)
  • +1我不知道语法允许这个. (2认同)

Ser*_*rez 8

您可以使用范围来遍历,它可以是数组、字符串、输入行或列表。

在此示例中,我使用了一个数字列表 [0..10],增量也为 2。

#!/bin/bash
for i in {0..10..2}; do 
   echo " $i times"
done
Run Code Online (Sandbox Code Playgroud)

输出是:

 0 times
 2 times
 4 times
 6 times
 8 times
 10 times
Run Code Online (Sandbox Code Playgroud)

要打印索引而不管循环范围如何,您必须使用变量“COUNTER=0”并在每次迭代“COUNTER+1”中增加它。

我的解决方案打印每次迭代,FOR 遍历输入行并每次迭代递增 1,还显示输入行中的每个单词:

#!/bin/bash 

COUNTER=0
line="this is a sample input line"

for word in $line; do        
    echo "This i a word number $COUNTER: $word"
    COUNTER=$((COUNTER+1))
done
Run Code Online (Sandbox Code Playgroud)

输出是:

This i a word number 0: this
This i a word number 1: is
This i a word number 2: a
This i a word number 3: sample
This i a word number 4: input
This i a word number 5: line
Run Code Online (Sandbox Code Playgroud)

要查看有关循环的更多信息:在此处输入链接描述

测试您的脚本:在此处输入链接描述


Gra*_*ham 5

n=0
cat test.txt | while read line; do
  printf "%7s %s\n" "$n" "${line#*//}"
  n=$((n+1))
done
Run Code Online (Sandbox Code Playgroud)

当然,这也适用于 Bourne shell。

如果您确实想避免递增变量,可以通过 grep 或 awk 管道输出:

cat test.txt | while read line; do
  printf " %s\n" "${line#*//}"
done | grep -n .
Run Code Online (Sandbox Code Playgroud)

或者

awk '{sub(/.*\/\//, ""); print NR,$0}' test.txt
Run Code Online (Sandbox Code Playgroud)