Bash循环,打印当前迭代?

时间:2012-06-08 03:44:39

标签: bash loops while-loop

假设你有一个简单的循环

while read line
do
  printf "${line#*//}\n"
done < text.txt

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

这样的东西
0 The
1 quick
2 brown
3 fox

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

5 个答案:

答案 0 :(得分:25)

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

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

编辑:经过多次考虑之后,如果你有bash版本4或更高版本,你可以在没有计数器的情况下完成:

mapfile -t arr < test.txt
for i in "${!arr[@]}"; do
   printf '%d %s' "$i" "${arr[i]}"
done

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

答案 1 :(得分:13)

您不经常看到它,但您可以在while循环的条件子句中拥有多个命令。以下仍然需要一个明确的计数器变量,但这种安排可能更适合某些用途或吸引人。

while ((i++)); read -r line
do
    echo "$i $line"
done < inputfile

最后一个命令返回的任何内容都满足while条件(在这种情况下为read)。

有些人更喜欢将do包含在同一行。这就是看起来的样子:

while ((i++)); read -r line; do
    echo "$i $line"
done < inputfile

答案 2 :(得分:2)

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

当然,这也适用于Bourne shell。

如果你真的想避免增加变量,你可以通过grep或awk管道输出:

cat test.txt | while read line; do
  printf " %s\n" "${line#*//}"
done | grep -n .

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

答案 3 :(得分:1)

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

在此示例中,我使用的数字列表[0..10]也以2递增。

public static IThing Pop(this List<IThing> list)
{
  if (list == null || list.Count == 0) return default(IThing);

  // get last item to return
  var thing = list[list.Count - 1];
  // remove last item
  list.RemoveAt(list.Count-1);

  return thing;
}

public static IThing Peek(this List<IThing> list)
{
  if (list == null || list.Count == 0) return default(IThing);

  // get last item to return
  return list[list.Count - 1];
}

public static void Remove(this List<IThing> list, IThing thing)
{
  if (list == null || list.Count == 0) return;
  if (!list.Contains(thing)) return;

  list.Remove(thing); // only removes the first it finds
}

public static void Insert(this List<IThing> list, int index, IThing thing)
{
  if (list == null || index > list.Count || index < 0) return;

  list.Insert(index, thing);
}

输出为:

#!/bin/bash
for i in {0..10..2}; do 
   echo " $i times"
done

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

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

 0 times
 2 times
 4 times
 6 times
 8 times
 10 times

输出为:

#!/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

查看有关循环的更多信息:enter link description here

测试脚本:enter link description here

答案 4 :(得分:0)

更新:此处发布的其他答案更好,特别是@Graham和@DennisWilliamson的答案。

非常喜欢这样的东西应该适合:

tr -s ' ' '\n' <test.txt | nl -ba

如果要从0开始编制索引,可以在-v0命令中添加nl标志。