【问题标题】:wc -l Sometimes Outputs Wrong Numberwc -l 有时会输出错误的数字
【发布时间】:2017-02-27 16:36:18
【问题描述】:

我有一些这样的代码:

while true
do
    who | cut -d' ' -f1 | sort | grep -v "erik" > "/home/erik/logintester/users.txt"

    lines=$(< "/home/erik/logintester/users.txt" wc -l)

    echo "$lines"

done

当有其他人登录时,它应该回显一个“1”,但我却得到了 1 和 0 的混合。有解决这个问题的方法吗?任何建议都非常感谢。

【问题讨论】:

  • wc -l 错误的情况下提供users.txt 的副本。虽然您应该真的使用mktemp 来确保此脚本的每个副本都有自己的、唯一的临时文件副本(如果您要使用的话)。
  • 如果你想要唯一的用户,你应该使用sort -ugrep -v "erik" 也是一个糟糕的正则表达式,因为它会过滤掉包括“erik”在内的其他用户,比如“erika”、“erikssen”等。你可能想用“^erik$”之类的东西进行 grep。
  • @vdavid 感谢您的建议!我会记住这一点的。

标签: bash shell wc


【解决方案1】:

假设 BOC 关于第二个进程干扰的建议是正确的,那么您正在通过使用不必要的文件(该文件提供允许竞争条件发生的共享资源)来促成问题。

您只需要一条管道即可。 (为了调用echo而捕获管道的输出也是不必要的。)

while true; do
    who | cut -d' ' -f1 | sort | grep -v "erik" | wc -l
done

您可以通过对awk 的一次调用来进一步简化它(sort 似乎没有任何用途;无论输出的顺序如何,计数都是相同的):

while true; do
    who | awk '$1 != "erik" {count+=1} END {print count}'
done

【讨论】:

  • sort 允许获取唯一用户。我猜 Erik 忘了把它传给uniq 或打电话给sort -u。同样awk 是矫枉过正,grep -c -v erik 给出相同的结果并且可能更有效。
  • 非常感谢您的帮助!
【解决方案2】:

您有另一个同时运行的代码实例。检查正在运行的进程并杀死前一个。

命令

who | cut -d' ' -f1 | sort | grep -v "erik" > "/home/erik/logintester/users.txt"

不是原子的。它首先创建一个空文件 users.txt,然后为管道的每个命令创建所有进程,然后将这些进程写入文件。这给出了文件为空的时间流逝。当您有两个进程运行相同的代码时,一个进程很有可能会显示另一个进程创建的空文件的内容。

避免像@chepner 建议的那样使用临时文件总是一个好主意。

【讨论】:

  • 成功了!为什么会这样?你会好心编辑你的问题吗?非常感谢您的帮助!
  • 我真的很想接受你的两个答案!
猜你喜欢
  • 1970-01-01
  • 2023-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-30
  • 1970-01-01
  • 2020-04-11
相关资源
最近更新 更多