假设你有一个简单的循环:
while read line
do
printf "${line#*//}\n"
done < text.txt
有没有一种优雅的方法可以将当前迭代次数与输出一起打印出来?就像这样:
0 The 1 quick 2 brown 3 fox
我希望避免在每个循环中设置一个变量并对其进行递增。
假设你有一个简单的循环:
while read line
do
printf "${line#*//}\n"
done < text.txt
有没有一种优雅的方法可以将当前迭代次数与输出一起打印出来?就像这样:
0 The 1 quick 2 brown 3 fox
我希望避免在每个循环中设置一个变量并对其进行递增。
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内置函数将文件的全部内容读入数组中。然后,您可以遍历该数组的索引,这些索引将是行号,并访问该元素。
虽然不常见,但是你可以在 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
for
做的事情类似: for ((i=0, j=14; i<=20; i++, j+=11))
。另外,你可以一次读取文件中的两行(或更多行):while read -r oddline; read -r evenline; do echo "odd: [$oddline] even: [$evenline]"; done < filename
。 - Dennis Williamson您可以使用范围进行遍历,它可以是数组、字符串、输入行或列表。
在此示例中,我使用数字列表 [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
#!/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
了解更多关于循环的内容,请访问:此链接
测试你的脚本,请访问:此链接
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
sub(/.*\/\//, "");
并不等同于 ${line#*//}
。 - ghoticat
命令无用,而且没有使用 -r
选项的 read
命令会破坏输入中的反斜杠。这是重新实现 nl
的一种非常低效的方式。 - tripleee更新:这里发布的其他答案更好,特别是@Graham和@DennisWilliamson的答案。
类似于这样的东西应该适合:
tr -s ' ' '\n' <test.txt | nl -ba
如果您想从0开始索引,可以在nl
命令中添加-v0
标志。
//
的行,就像${line#*//}
那样。但是你肯定可以通过nl
将while循环管道化,就像我在我的答案中使用grep -n .
一样。 - Graham
mapfile
可能会非常耗费内存。不知道原帖中的文件大小,我建议使用通过管道运行的方法,这样它对文件大小是不敏感的。 - ghoti