我有一个由第一个字段编辑的文本文件sort
,即月/日(例如:02-20)
我一直grep
在文本文件上使用,但使用date
脚本中的命令来处理今天的日期是最简单的。
我想提取前 3 天、今天的日期和未来 5 天的数据...但我不知道处理月底/下个月的简单方法。我想,我可以将其硬编码进去吗?但我一直在寻找解决问题的优雅方法,所以我正在寻求建议。
我更喜欢使用常规命令,以便脚本尽可能可移植。
即:通过便携式,我的意思不仅限于 Linux/GNU 机器(和/或必须安装特定的实用程序才能使一切运行)。目前我认为我使用的是 BSD 机器,并且我已经使用过大多数 UNIX 风格(Solaris,等等,等等,等等)——并且可能将来也会如此。
我会采用一些更复杂的程序/脚本,使用非常基本的工具,而不是每次我可能使用不同风格的 UNIX 时都必须记住安装软件包(当我可以在我的脚本目录中进行 scp 并让它工作时) )。
仅供参考:当前的date
-d 标志设置夏令时:)
-d dst Set the system's value for Daylight Saving Time.
好的,我只是给出了一个文件中数据类型的示例(按要求)(它要大得多,obvs),但我没有给出边缘情况。这是一个边缘情况,即:如何处理月末期间,而无需在月末测试中针对每个月(或 4 种类型的月份:30、31、28 和 29)进行编程。
01-01 Something To Do Here Notes that may run for a really long time
02-05 On the 5th of the Month Do this other thing, because of X
02-06 The day after Do this cleanup stuff
03-15 The Ides Remember, remember the Brutus of December
03-29 Edge Does this show up on the 1st of April?
03-30 Edge2 Does this show up on the 1st and 2nd?
03-31 Last day in the month Shows?
04-01 Edge Does this show on 31st? Or does it only show 03-35?
答案1
GNU date 允许您为选项提供字符串,-d
例如-2 days
和5 days
。该-f
选项允许从文件或管道读取这些字符串。所以使用 GNUdate
和bash
:
printf '%d days\n' {-2..5} | date -f - +%m-%d | grep -f - in_file
更新
如果tcl
可以接受,这里有一个打印日期的脚本:
#!/usr/bin/tclsh
set now [clock seconds]
for {set n -2} {$n<=5} {incr n} {
set out_date [clock add $now $n days]
puts [clock format $out_date -format %m-%d]
}
只需将其输出通过管道传递到grep -f -
上面即可。
答案2
好吧,这里有一个衬里似乎可以完成这项工作......
dt=$(date +%m-%d);for i in {-2..5}; do grep "$(echo "$dt"|awk -F"-" -v count=$i '{print $1"-0"$2+count}')" mtest; done
您可以通过将其添加到 .bashrc 中来使其成为一个函数...
todolist(){ dt=$(date +%m-%d);for i in {-2..5}; do grep "$(echo "$dt"|awk -F"-" -v count=$i '{print $1"-0"$2+count}')" $1; done; }
然后你就可以称之为
todolist whateverthefilename.txt
它不是很漂亮,但我用你的数据测试了它确实有效。
$ echo -e "01-01 Something To Do Here Notes that may run for a really long time\n02-05 On the 5th of the Month Do this other thing,\nbecause of X\n02-06 The day after Do this cleanup stuff\n03-15 The Ides Remember, remember the Brutus of December">> mtest
$ dt=02-05; for i in {-2..5}; do grep "$(echo "$dt"|awk -F"-" -v count=$i '{print $1"-0"$2+count}')" mtest; done
02-05 On the 5th of the Month Do this other thing,
02-06 The day after Do this cleanup stuff
答案3
您可以使用touch
POSIXLY 测试日期字符串的有效性。
我将在这里使用几个选项。
-c
- 不创建指定的文件如果它不存在。不要写任何有关此情况的诊断消息。
-t
使用指定时间而不是当前时间。选项参数应为以下形式的十进制数:
[[CC]YY]MMDDhhmm[.SS]
如果时间无法表示为文件的时间戳,
touch
则应立即退出并显示错误状态。- 请注意,这些
[[CC]YY]
字段是可选的。
因此,例如:
testtime()
if command -v touch >&2
then touch -c ''
eval ' touch -ct"$1" ""
[ "$?" = '"$? ]"
else { touch; } 2>&3
fi 3>&2 2>/dev/null
我认为,处理可移植的事情是相当小心的。在 GNU 和传家宝的测试中(索拉里斯) touch
,GNU 工具对于错误日期返回 1,对于良好日期返回 0,但传家宝版本分别返回 2 和 1。我相当确定旧的 Solaris 工具的行为在规范的基本原理中得到了特别引用,我发现:
- 如果指定且文件不存在,至少有一种历史实现会
touch
增加退出代码。-c
如果没有发生错误,本卷 POSIX.1-2008 要求退出状态为零。
当我比较我的传家宝工具的不同版本的行为时,我更加确信了。基本集合中的一个 - 其设计的行为尽可能与原始集合相似,并且在现代系统上仍然有用 - 是返回如上所述的 2 和 1 的那个。但是,当我使用/usr/heirloom/bin/posix2001/touch
可执行文件时(该版本已根据需要进行了标准合规性修改),它的返回与 GNU 工具完全相同。
在任何情况下,该函数都可以处理旧的 Solaris、经过修改的 Solaris 和 GNU 行为,因为它将初始调用的结果与touch
空''
文件操作数进行比较(这绝对不存在)反对第二次调用同一日期,并返回 0 表示良好的日期或 1 表示糟糕的日期。如果touch
找不到,它会返回 127 并写入 stderr 。
使用方法如下:
testtime MMDD0000 && echo good date || echo bad date
...在哪里毫米和DD是 2 位十进制字符串,表示您要测试的日期。您还可以通过这种方式检查有效时间 - 甚至可以使用.S
秒字段。
答案4
我昨天发布了我的第一个答案,睡眠太少了。我回来了,准备再试一次。我没有尝试对日期进行 awk,而是认为自己太聪明了,所以我回去重新考虑了。
todolist(){ for i in {-2..5}; do grep "$(date -d "${date} +$i days" +%m-%d)" $1 ; done; };
只需将一行代码添加到 .bashrc 中,然后将文件提供给它即可。
这次我让约会做所有的工作。我拿到从这里提示。这一点将从今天开始添加任意天数,并以您的文件所需的格式输出......
date -d "${date} +$i days" +%m-%d)"
上面的函数现在应该可以工作,而无需求助于硬编码值。