【问题标题】:why does this for loop only loop once?为什么这个for循环只循环一次?
【发布时间】:2020-05-28 08:28:50
【问题描述】:

我想做的是一个简单的练习代码,输出如下:

user1 logged in at hh:mm
user2 logged in at hh:mm
...

所以我写了一个基本的 for 循环,但我不明白为什么它只运行一次。

for user in $(who)
do
    USERID=$(echo $user | tr -s ' ' | cut -d' ' -f1)
    LOGTIME=$(echo $user | tr -s ' '| cut -d' ' -f4)
    echo "$USERID logged in at $LOGTIME"
done

这与以下内容相呼应:

user1
user2
user3 logged in at hh:mm
hh:mm
hh:mm

我已经在两者之间放置了回显线来弄清楚发生了什么以及如何修复它,但我唯一发现的是 for 循环只运行一次,所以 USERID 和 LOGTIME 只是一个长字符串换行符。我究竟做错了什么? (我做了 IFS=$'\n')

【问题讨论】:

  • 尝试使用 while 循环而不是 for 来阅读。 while read user do echo $user done < $(who)
  • @DigvijayS 这对我不起作用。出于某种原因,它在 $(who) 上给了我一个“没有这样的文件或目录”错误

标签: bash shell unix


【解决方案1】:

请您尝试以下方法:

while read -r user tty mon day logtime; do
    echo "$user logged in at $logtime"
done < <(who)

【讨论】:

  • 谢谢!但我不得不稍微改变一下。结果是“默认的谁(用户 ID + 等)登录”,没有登录时间。所以我把问题中的 USERID 和 LOGTIME 代码放在 do-done 语句之间,更改了 echo 语句,它就起作用了!再次感谢您的帮助!
【解决方案2】:
#!/bin/sh

who > stack

while [ $(wc -l stack) -gt 0 ]
do
  line=$(sed '1p' stack)
  USERID=$(echo ${line} | tr -s ' ' | cut -d' ' -f1)
  LOGTIME=$(echo ${line} | tr -s ' '| cut -d' ' -f4)
  echo "${USERID} logged in at ${LOGTIME}"
  sed -i '1d' stack
done

rm -v ./stack
exit 0

如果这不起作用,请提供一个示例,说明谁在您的机器上输出。

【讨论】:

  • 这是非常低效的。 @DigvijayS 有正确的想法。
  • 它在做什么也是透明的。如果 OP 决定他不想使用它,那么这取决于他;但你的陈述被拒绝了。
  • 我明白这是要做什么,但我必须同意@l0b0,即它对于我想要实现的目标有点低效。尽管如此,谢谢你的建议!