【发布时间】:2021-02-12 04:27:34
【问题描述】:
我们有一些 |分隔的输入 CSV 文件。我们的要求是,如果最后一个字段值包含 9999-12-31,那么我们需要从第二个字段中减去 3 天并保持最后一个字段不变。如果最后一个字段值没有 9999-12-31,则从最后一个字段和倒数第二个字段中减去 3 天。
示例输入文件:-
#Code|sequence|Code_ID|margin_ID|Eff_date|End_date
M|X19|0002|F3|2020-12-10|9999-12-31
M|X19|0002|F3|2021-01-15|9999-12-31
M|X19|0002|F3|2010-10-10|2019-11-09
M|X19|0002|F3|2010-03-09|2011-04-02
预期的输出文件:-
#Code|sequence|Code_ID|margin_ID|Eff_date|End_date
M|X19|0002|F3|2020-12-07|9999-12-31
M|X19|0002|F3|2021-01-12|9999-12-31
M|X19|0002|F3|2010-10-07|2019-11-06
M|X19|0002|F3|2010-03-06|2011-03-30
谁能建议使用脚本或命令来获得预期的输出?
我正在尝试使用以下命令,但出现错误。
for i in `ls *.csv`
do
awk -F"|" -v OFS="|" '{if(NR>1) { if ($NF~/9999-12-31/) { $(NF-1)="date -d \"$(date -d \""$(NF-1)"\")-3days\" \"+%Y-%m-%d \""; print $0}
else {$(NF-1)="date -d \"$(date -d \""$(NF-1)"\")-3days\" \"+%Y-%m-%d \""; $NF="date -d \"$(date -d \""$NF"\")-3days\" \"+%Y-%m-%d \"";
print $0} } }' $i >> temp/new_$i
done
获取 awk:第 1 行附近的语法错误
由 Ed Morton 编辑我通过gawk -o-(漂亮的打印)运行上述 awk 脚本以使其清晰易读,这是更清晰的结果:
{
if (NR > 1) {
if ($NF ~ /9999-12-31/) {
$(NF - 1) = "date -d \"$(date -d \"" $(NF - 1) "\")-3days\" \"+%Y-%m-%d \""
print $0
} else {
$(NF - 1) = "date -d \"$(date -d \"" $(NF - 1) "\")-3days\" \"+%Y-%m-%d \""
$NF = "date -d \"$(date -d \"" $NF "\")-3days\" \"+%Y-%m-%d \""
print $0
}
}
}
【问题讨论】:
-
修复“第 1 行附近的语法错误”的第一步是编写脚本,使其占据多行,使其具有一定的可读性。就目前而言,它几乎是完全难以理解的,因为它不可读。
-
将一个大脚本塞进 1 行总是一个坏主意,原因有很多,其中一个原因是您收到的每条错误消息都会告诉您错误在第 1 行,这是没有用的。话虽如此 - 你的脚本不包含任何语法错误,所以要么你没有发布你运行的脚本,要么调用 shell 脚本有问题,或者你的 awk 坏了(例如,让它变旧、坏了 awk - /bin/在 Solaris 上使用 awk)。