文本处理:基于另一个列值偏移列中的日期值

时间:2019-05-22 12:10:26

标签: awk

我在第4列中有一个文本文件,其日期值为YYYYMMDD格式,在第5列中有一个月的偏移量。

System.Data.SqlClient is not supported on this platform

我想将第5列中的值替换为 日期-d'(第4列中的值)-(第5列中的值)月+1个月'+'%Y%m%d'

因此最终结果应如下所示

a1|b1|c1|20190101|1|1|11|A|D
a1|b1|c1|20190101|2|2|12|B|E
a1|b1|c1|20190101|3|3|13|C|F
a2|b2|c2|20190101|1|4|14|G|J
a2|b2|c2|20190101|2|5|15|H|K
a2|b2|c2|20190101|3|6|16|I|L

我使用awk -f offsetMonths.awk绑定

a1|b1|c1|20190101|20190101|1|11|A|D
a1|b1|c1|20190101|20181201|2|12|B|E
a1|b1|c1|20190101|20181101|3|13|C|F
a2|b2|c2|20190101|20190101|4|14|G|J
a2|b2|c2|20190101|20181201|5|15|H|K
a2|b2|c2|20190101|20181101|6|16|I|L

我得到的是

BEGIN{
    FS="|"
    OFS = FS
}
{
#   Date field is in column 4, offset is in column 5
#   Replace column 5 with the offset date
    "date -d '"$4" -"$5" months +1 months'  +'%Y%m%d' " | getline l
    $5 = l
    print $0
}

请注意第4行到第6行中不正确的月份偏移值

3 个答案:

答案 0 :(得分:3)

除了kvantour答案(这可能比我的回答更干净,因为我更喜欢使用awk内置函数而不是在awk中调用bash命令),这是固定的代码:

df %>% as_tibble() %>% 
  mutate(Score = as.numeric(Score)) %>% 
  spread(Pre_Post, Score) %>%
  rename(Score_pre = `1`, Score_post = `2`) %>%
  mutate(improve = if_else(Score_pre > Score_post, "0", "1")) %>% 
  group_by(improve) %>% 
  summarise(n = n()) %>% 
  mutate(percentage = n / sum(n))

# A tibble: 2 x 3
  improve     n percentage
  <chr>   <int>      <dbl>
1 0           3      0.429
2 1           4      0.571

结果:

BEGIN{
    FS="|"
    OFS = FS
}
{
#   Date field is in column 4, offset is in column 5
#   Replace column 5 with the offset date

    cmd = "date -d '"$4" -"$5-1" months'  +'%Y%m%d'" # as suggested by @kvantour
    cmd | getline result
    close(cmd)
    $5 = result
    print $0
}

更多informations在这里。

  

在没有调用close()的情况下,awk会创建子进程来运行命令,直到最终用尽了用于更多管道的文件描述符为止。

答案 1 :(得分:3)

您无需为此调用外部char * buffer = new char[size + 1]; // size = 5, allocate 6 chars InternetReadFile(request, buffer, size, &dwRead); buffer [size] = '\0'; 实用程序或特定于gawk的时间函数,这只是数学上的事情:

date

答案 2 :(得分:2)

使用GNU awk,任何日期转换都应使用提供的日期函数执行。此问题的两个有用的时间函数是mktimestrftime

  
      
  • mktime(datespec) :将日期格式为datespec的字符串YYYY MM DD hh mm ss转换为Unix纪元时间,即总秒数自1970年1月1日UTC。从gawk-4.2.1开始,您可以使用utc-flag来指示datespec是否使用UTC。

  •   
  • strftime(format,timestamp) :这会将历时timestamp转换为格式化的字符串(与date命令相同的格式)。您可以使用utc-flag指示返回的时间应采用UTC或当地时区。

  •   
     

GNU awk manual

中的更多信息

代码现在变为:convert.awk

BEGIN {FS=OFS="|"}
{ d=$4
  time=mktime(substr(d,1,4)" "substr(d,5,2)+1-$5" "substr(d,7,2)" 00 00 00")
  $5=strftime("%Y%m%d",time)
  print
}' file

,然后使用以下命令运行它:

$ awk -f convert.awk file.txt

mktime additive 。因此,您以YYYY MM DD hh mm ss格式传递的字符串不需要是正确的日期,您可以使用不正确的值。例如,字符串2019 01 32 00 00 00等效于2019 02 01 00 00 00,字符串2019 5 -10 00 00 00等效于2019 04 20 00 00 00,甚至2019 -19 -10 00 00等效于2017 04 20 00 00

注意:由于我们直接在mktime中修改了时间,因此我们不必担心夏令时(请参阅注释)。