【问题标题】:How does grep know it is writing to the input file?grep 如何知道它正在写入输入文件?
【发布时间】:2023-04-01 11:25:01
【问题描述】:

如果我尝试将grep 的输出重定向到它正在读取的同一文件,如下所示:

$ grep stuff file.txt > file.txt

我收到错误消息grep: input file 'file.txt' is also the outputgrep 是如何确定的?

【问题讨论】:

    标签: linux unix command-line grep


    【解决方案1】:

    根据 GNU grep 源代码,grep 检查输入和输出的 i 节点:

      if (!out_quiet && list_files == 0 && 1 < max_count
          && S_ISREG (out_stat.st_mode) && out_stat.st_ino
          && SAME_INODE (st, out_stat))   /* <------------------ */
        {
          if (! suppress_errors)
            error (0, 0, _("input file %s is also the output"), quote (filename));
          errseen = 1;
          goto closeout;
        }
    

    out_stat 是通过调用 fstat 来填充 STDOUT_FILENO

      if (fstat (STDOUT_FILENO, &tmp_stat) == 0 && S_ISREG (tmp_stat.st_mode))
        out_stat = tmp_stat;
    

    【讨论】:

    • 感谢您的回复,我忘记了 shell 是如何事先设置进程的文件描述符的,而 grep 可以检查这些信息。
    【解决方案2】:

    查看源代码 - 您可以看到它检查了这种情况(该文件已打开以供 grep 阅读)并报告它,请参阅下面的 SAME_INODE 检查:

      /* If there is a regular file on stdout and the current file refers
         to the same i-node, we have to report the problem and skip it.
         Otherwise when matching lines from some other input reach the
         disk before we open this file, we can end up reading and matching
         those lines and appending them to the file from which we're reading.
         Then we'd have what appears to be an infinite loop that'd terminate
         only upon filling the output file system or reaching a quota.
         However, there is no risk of an infinite loop if grep is generating
         no output, i.e., with --silent, --quiet, -q.
         Similarly, with any of these:
           --max-count=N (-m) (for N >= 2)
           --files-with-matches (-l)
           --files-without-match (-L)
         there is no risk of trouble.
         For --max-count=1, grep stops after printing the first match,
         so there is no risk of malfunction.  But even --max-count=2, with
         input==output, while there is no risk of infloop, there is a race
         condition that could result in "alternate" output.  */
      if (!out_quiet && list_files == 0 && 1 < max_count
          && S_ISREG (out_stat.st_mode) && out_stat.st_ino
          && SAME_INODE (st, out_stat))
        {
          if (! suppress_errors)
            error (0, 0, _("input file %s is also the output"), quote (filename));
          errseen = true;
          goto closeout;
        }
    

    【讨论】:

      【解决方案3】:

      这里是写回某个文件的方法:

      grep stuff file.txt > tmp && mv tmp file.txt
      

      【讨论】:

        【解决方案4】:

        尝试使用 cat 或 tac 进行管道:

            cat file | grep 'searchpattern' > newfile
        

        这是最佳实践,是实现的缩写

        【讨论】:

          猜你喜欢
          • 2015-09-01
          • 1970-01-01
          • 2015-07-13
          • 1970-01-01
          • 2017-06-26
          • 1970-01-01
          • 2019-07-03
          • 2011-07-17
          • 2021-02-17
          相关资源
          最近更新 更多