【问题标题】:Insert or update a row in a text file在文本文件中插入或更新一行
【发布时间】:2021-10-19 18:35:57
【问题描述】:

我想将一个值写入带有时间戳的文本文件。数据/值每隔几分钟更新一次,但我只想记录最后一个值及其日期。第二天我想重新开始新的一行,但保留以前的值。然后将输出图表显示每日值。

我可以使用 if、then、else 循环来做到这一点,但我想有一个更优雅的 awk、sed、'something' 解决方案。

这将由 cron 作业运行。

第 1 天。 每 5 分钟插入一行 $date, $value

在同一天继续更新该行

第 2 天。 插入新行并重复

期望的输出

第 1 天上午 10 点

2021-08-17, 5.20

第 1 天晚上 11 点

2021-08-17, 12.10

第 2 天上午 10 点

2021-08-17, 12.10
2021-08-18, 4.90

第 2 天晚上 11 点

2021-08-17, 12.10
2021-08-18, 13.10

【问题讨论】:

  • 到目前为止你尝试过什么(代码)?
  • 我可以用 if, then, else 循环来做到这一点 没有 if-then-else-loop。 bash 中的循环是使用 forwhileselect 完成的。

标签: bash shell cron


【解决方案1】:

一个想法是跳过/忽略/删除带有今天日期的行(如果存在),然后添加一个带有今天日期的新行。

示例数据文件:

$ cat date.log
2021-08-14, 23.1
2021-08-15, 17.3
2021-08-16, 9.3

$ today=$(date '+%Y-%m-%d')
$ echo $today
2021-08-17

$ newvalue=13.2

一个sed的想法来实现这个逻辑:

$ sed -i -n -e "/^${today}, .*$/"'!p' -e '$a'"${today}, ${newvalue}" date.log

地点:

  • -i -n -e - -inplace 更新源文件,-n 禁止自动打印图案空间,-e 指定一段脚本
  • "/^${today}, .*$/" - 搜索匹配的模式(行首)+ ${today} + , + 其余行;需要使用双引号,以便将${today} 替换为其实际值
  • '!p' - 反向模式搜索和打印行(即,打印除与^${today}, .*$ 匹配的行之外的所有内容);需要使用单引号,因为双引号中的!p 将替换为以字母p 开头的最后一个历史命令
  • -e '$a' - 另一段找到文件结尾的脚本 ($) 和 a追加以下字符串;必须使用单引号,以便 bash 不会尝试将文字 $a 替换为变量 a 的内容
  • "${today}, ${newvalue}" - 附加到文件末尾的字符串

如果我们在 sed 调用前加上 set -xv(启用调试模式),我们会看到控制台上打印了以下内容:

+ sed -i -n -e '/^2021-08-17, .*$/!p' -e '$a2021-08-17, 13.2' date.log

还有我们文件的内容:

$ cat date.log
2021-08-14, 23.1
2021-08-15, 17.3
2021-08-16, 9.3
2021-08-17, 13.2              # new line appended to file

再运行几次(发出set +xv 以禁用调试模式后):

$ newvalue=32.7
$ sed -i -n -e "/^${today}, .*$/"'!p' -e '$a'"${today}, ${newvalue}" date.log
$ cat date.log
2021-08-14, 23.1
2021-08-15, 17.3
2021-08-16, 9.3
2021-08-17, 32.7              # updated (really deleted and appended)

$ newvalue=73.xxx
$ sed -i -n -e "/^${today}, .*$/"'!p' -e '$a'"${today}, ${newvalue}" date.log
$ cat date.log
2021-08-14, 23.1
2021-08-15, 17.3
2021-08-16, 9.3
2021-08-17, 73.xxx            # updated (really deleted and appended)

$ today='2021-09-23'
$ newvalue=7.25
$ sed -i -n -e "/^${today}, .*$/"'!p' -e '$a'"${today}, ${newvalue}" date.log
$ cat date.log
2021-08-14, 23.1
2021-08-15, 17.3
2021-08-16, 9.3
2021-08-17, 73.xxx
2021-09-23, 7.25              # new line appended to file

【讨论】:

  • 谢谢@markp-fuso - 这正是我所追求的。并感谢您详细而清晰的解释 - 非常感谢
【解决方案2】:

使用两个不同的 cronjob 条目。一个在每天开始时运行,使用ed 或其他任何内容向文件添加新行:

# Something that sets date and value here
printf "%s\n" '$a' "$date, $value" . w | ed -s /your/file.txt

另一个每 5 分钟运行一次,并用新值替换文件的当前最后一行:

# Something that sets date and value here
printf "%s\n" '$c' "$date, $value" . w | ed -s /your/file.txt

【讨论】:

    【解决方案3】:

    使用 GNU awk 的-i inplace capable version

    $ gawk -i inplace -v d=2021-08-17 -v v=12.20 '    # new data in parameters
    @load "filefuncs"                                 # for stat to detect missing file
    BEGIN {
        if(ARGC==1)                                   # if no file given
            exit 1                                    # exit with an error
        FS=OFS=", "                                   # set the field separators
        # d=strftime("%F")                            # no need parameterize the date
        if(stat(ARGV[1],fdata)<0) {                   # if given file does not exist
            print d,v > ARGV[1]                       # create it
            exit                                      # and exit
        }
    }
    {
        if(NR>1)                                  
            print pd,pv                               # print previous data record
        pd=$1                                         # store current for next round
        pv=$2
    }
    ENDFILE {                                         # in the end
        if(pd!=d)                                     # if dates differ
            print pd,pv                               # print previous
        print d,v                                     # print given data
        exit                                          # to skip over following files
    }' file
    

    【讨论】:

      猜你喜欢
      • 2012-09-19
      • 1970-01-01
      • 1970-01-01
      • 2021-11-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-15
      相关资源
      最近更新 更多