32

假设你有一个简单的循环

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

有没有用输出打印当前迭代的优雅方法?就像是

0 的
1 快速
2棕色
3 狐狸

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

4

5 回答 5

57

为此,您需要在每次迭代时增加一个计数器(就像您试图避免的那样)。

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 将文件的全部内容读入数组。然后,您可以遍历数组的索引,这将是行号并访问该元素。

于 2012-06-08T04:41:51.177 回答
23

你不经常看到它,但你可以在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
于 2012-06-08T11:22:30.857 回答
4
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
于 2012-06-08T04:57:57.243 回答
4

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

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

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

输出是:

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

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

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

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

输出是:

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

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

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

于 2018-08-05T01:59:21.647 回答
1

更新: 这里发布的其他答案更好,尤其是@Graham 和@DennisWilliamson 的答案。

像这样的东西应该适合:

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

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

于 2012-06-08T04:00:47.893 回答