【问题标题】:How to omit first column in the terminal output and parallely write the output (along with omitted first column) in a file using unix?如何省略终端输出中的第一列并使用 unix 将输出(连同省略的第一列)并行写入文件中?
【发布时间】:2018-05-18 09:39:45
【问题描述】:

我被困在下面的场景中。

我已将这些添加到一个名为:small_script.sh 的脚本中

#!/bin/bash

uname
uname -r
uname -a
pwd

我需要终端中显示的每一行的时间戳(以秒为单位),并且需要写入文件。因此我实现如下:

./small_script.sh | while read R; do echo "$(date +%s) $R"; done | tee output.txt

1526635998 Darwin
1526635998 17.4.0
1526635998 Darwin C02V41QWHV2R 17.4.0 Darwin Kernel Version 17.4.0 ..
1526635998 /Users/home/duraja

现在,我的查询是我在终端中寻找输出,其中第一列(日期以秒为单位)不显示,但第一列(日期以秒为单位)应该在我的文本文件中。

样本输出期望..

终端输出应该显示

Darwin
17.4.0
Darwin C02V41QWHV2R 17.4.0 Darwin Kernel Version 17.4.0 ..
/Users/home/duraja

文本文件输出应该显示

1526635998 Darwin
1526635998 17.4.0
1526635998 Darwin C02V41QWHV2R 17.4.0 Darwin Kernel Version 17.4.0 ..
1526635998 /Users/home/duraja

我怎样才能实现它?请提出建议。

【问题讨论】:

  • 如果您能在帖子中告诉我们您的示例输入和示例预期输出,我们可以在这方面为您提供更多帮助。
  • 请检查我的答案一次,让我们知道这是否有帮助?否则,请在您的帖子中发布示例,其中包含您问题的所有详细信息,以便更好地理解。,
  • 嗨@RavinderSingh13 ..我已经更新了输出。请建议。谢谢
  • 请检查我编辑的答案,然后告诉我?
  • 要清楚 - 您是在寻找脚本产生第一行输出的时间还是产生每一行输出的时间?如果您在发布的示例中添加了一些“sleep 1”,那么您想要的会更清楚。

标签: shell unix awk sed tee


【解决方案1】:

您可以在tee 命令之后使用sed 删除时间戳:

./small_script.sh | while read R; do echo "$(date +%s) $R"; done | tee output.txt | sed 's/^[^ ]\+ //'

sed 正则表达式匹配所有内容,直到行首的空格。

【讨论】:

  • 嗨奥利夫,它不工作。此外,时间戳应在脚本执行时保留,该时间戳应与文本文件中的时间戳相同。希望我能够正确地表达我的上下文。
  • @duraja 什么不工作?终端输出不显示时间戳,文件显示。这不是你想要的吗?
  • 是的@oliv 你是对的。但是您提供的输出仍然在终端输出中显示时间戳。我在描述中添加了示例输出供您参考。
  • @duraja 可能您使用的sed 版本不接受正则表达式,请将sed 命令替换为cut -d " " -f2-
【解决方案2】:

由于您没有在帖子中分享完整的要求、示例输入或示例输出,您能否尝试以下操作(根据您提供的代码和问题),其中第一列将打印到 @ 987654321@ 和该行的其余部分将打印在终端上。

./small_script.sh | 
awk -v date=$(date +%s) '{print $0 OFS date > "output_file";print}' 

【讨论】:

  • 终端输出省略了第一列(日期),但在输出文本文件中,只有最后一行得到文本文件中的时间戳。
  • @duraja,现在检查我编辑的答案然后让我知道吗?
【解决方案3】:

你可以在 tee 命令之后使用 cut 命令:

./small_script.sh | while read R; do echo "$(date +%s) $R"; done | tee output.txt | cut -c12-

【讨论】:

    【解决方案4】:

    请参阅https://unix.stackexchange.com/questions/169716/why-is-using-a-shell-loop-to-process-text-considered-bad-practice 了解一些避免使用 shell 循环执行此操作的原因。

    假设基于您问题中的循环,您想要生成每个输出行时的时间戳,而不是生成第一行时的时间戳(这将是微不足道的),并给出以下 shell 脚本:

    $ cat ./small_script.sh
    uname
    sleep 1
    uname -r
    sleep 1
    uname -a
    sleep 1
    pwd
    

    使用 shell 和 xargs(其中可能有一些 bash-isms/gnu-isms):

    $ ./small_script.sh | xargs -d$'\n' -I {} sh -c 'printf "%s\n" "{}"; printf "%s %s\n" "$(date +"%s")" "{}" >&2' 2>outfile1
    CYGWIN_NT-6.1
    2.9.0(0.318/5/3)
    CYGWIN_NT-6.1 Foo 2.9.0(0.318/5/3) 2017-09-12 10:18 x86_64 Cygwin
    /home/Ed
    
    $ cat outfile1
    1526673758 CYGWIN_NT-6.1
    1526673759 2.9.0(0.318/5/3)
    1526673760 CYGWIN_NT-6.1 Foo 2.9.0(0.318/5/3) 2017-09-12 10:18 x86_64 Cygwin
    1526673761 /home/Ed
    

    使用 GNU awk 进行时间函数:

    $ ./small_script.sh | awk '{print systime(), $0 > "outfile2"} 1'
    CYGWIN_NT-6.1
    2.9.0(0.318/5/3)
    CYGWIN_NT-6.1 Foo 2.9.0(0.318/5/3) 2017-09-12 10:18 x86_64 Cygwin
    /home/Ed
    
    $ cat outfile2
    1526673256 CYGWIN_NT-6.1
    1526673257 2.9.0(0.318/5/3)
    1526673258 CYGWIN_NT-6.1 Foo 2.9.0(0.318/5/3) 2017-09-12 10:18 x86_64 Cygwin
    1526673259 /home/Ed
    

    以及任何 awk:

    $ ./small_script.sh | awk '{cmd="date +\"%s\""; date=( (cmd | getline line) > 0 ? line : "ERR"); close(cmd); print date, $0 > "outfile3"} 1'
    CYGWIN_NT-6.1
    2.9.0(0.318/5/3)
    CYGWIN_NT-6.1 Foo 2.9.0(0.318/5/3) 2017-09-12 10:18 x86_64 Cygwin
    /home/Ed
    
    $ cat outfile3
    1526673404 CYGWIN_NT-6.1
    1526673405 2.9.0(0.318/5/3)
    1526673406 CYGWIN_NT-6.1 Foo 2.9.0(0.318/5/3) 2017-09-12 10:18 x86_64 Cygwin
    1526673407 /home/Ed
    

    【讨论】:

      【解决方案5】:

      您可以使用cut 从数据中拆分秒数。我将R 更改为小写,使用read-r 选项并使用printf,这些都是偏离主题的改进。

      ./small_script.sh |while read -r r; do
         printf "%s %s\n" $(date +%s) "$r"
      done | tee output.txt | cut -d" " -f2-
      

      您已经可以在循环中拆分输出。
      您可以使用 stderr 写入终端

      ./small_script.sh |while read -r r; do
         >2 printf "%s\n" "$r"
         printf "%s %s\n" $(date +%s) "$r"
      done > output.txt 
      

      缺点是输出到 stderr,因此重定向终端输出或使用 |more 与您的预期不同。
      当你在循环内用秒重定向行时,你应该首先删除输出文件(当它存在时)

      test -f output.txt && rm -f output.txt
      ./small_script.sh |while read -r r; do
         printf "%s\n" "$r"
         printf "%s %s\n" $(date +%s) "$r" >> output.txt
      done 
      

      【讨论】:

        猜你喜欢
        • 2011-11-11
        • 1970-01-01
        • 1970-01-01
        • 2012-06-15
        • 2014-04-03
        • 2017-10-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多