R系统调用awk失败

时间:2017-08-01 12:31:22

标签: r bash awk

我有一个日志文件,我们称之为mylogfile.txt

格式是 日期 - 时间戳,然后是分号分隔符,然后是我为此练习的目的而不关心的其他一些东西。

例如(这是日志文件中的所有一行 - 不确定如何在SO中表达如此道歉)

20170710-23:59:43.158;B@13.43434@1000000.0@20170710-21:15:53.23@@2017071023:59:43.158@@T@20170710-23:59:43.156#B@13.41834@4000000.0@20170710-21:15:53.23@@20170710-23:59:43.158@@T@20170710-23:59:43.156#A@13.47274@1000000.0@20170710-21:15:53.23@@20170710-23:59:43.158@@T@20170710-23:59:43.156#A@13.48874@4000000.0@20170710-21:15:53.23@@20170710-23:59:43.158@@T@20170710-23:59:43.156#

我目前正在尝试的只是一个概念验证示例。我希望解析文件,反转行顺序,并在输出中返回两列 -

1)只是从第一列解析的时间戳(这是一种日期 - 时间格式,所以我需要丢弃日期部分)

2)自午夜以秒为单位表示的时间戳,以毫秒精度表示(与时间戳本身的粒度一致。

所以从下面的单行示例中输出将是例如

23:59:43.158,86383.158

我可以半途而废。我可以使用语法来构造对awk的调用,该语法在cygwin中完美地运行(自然地剥离了R包装器)。但它在R

中不起作用
testawk<-paste0("tac ", mylogfile.txt, " | awk 'BEGIN {FS=\"-|;|:\"} {OMFT=\"%.3f\"} {print $2 \":\" $3 \":\" $4 \",\" (3600*$2)+(60*$3)+$4}' ")

getawk<-as.data.frame(system(testawk, intern=TRUE, show.output.on.console = FALSE))

然而,在数据框架getawk中结束的只是原始日志文件在正在读取时翻译。另外,我收到警告消息,即运行命令的状态为1。

无论其

如果我脱掉'tac'片而只是使用直awk,因此;

 testawk<-paste0("awk 'BEGIN {FS=\"-|;|:\"} {OMFT=\"%.3f\"} {print $2 \":\" $3 \":\" $4 \",\" (3600*$2)+(60*$3)+$4}' ", mylogfile.txt)

    getawk<-as.data.frame(system(testawk, intern=TRUE, show.output.on.console = FALSE))

我收到错误消息

Error in system(testawk, intern = TRUE, show.output.on.console = FALSE) : 'awk' not found

我不认为问题出在我的awk构造中,因为如果我只是在cygwin中执行它,它可以正常工作。所以很明显r / system / awk交互的一些方面我还没有完全掌握。

我想如果我把它全部包装在一个awk脚本中并简单地调用它可能有效,但我很沮丧我不能简单地找到正确的语法来直接用R系统命令调用awk(我处理grep,sed命令等等,好吧)。

它不像awk那样简单,实际上根本不受支持吗?

指针非常感谢。如果第一个说日志文件的20行是有用的,我也可以发布它们。

3 个答案:

答案 0 :(得分:1)

当尝试使用其他语言时,通常会发生这种情况,例如:蟒蛇。如果您还没有添加到Windows系统路径的路径,那么您还没有告诉RStudio在哪里可以找到可执行文件。

Cygwin的根通常位于C:\cygwin64(但可能因安装而异),因此找到安装并查找bin文件夹。应该有awk可执行文件,但它通常只是gawk可执行文件的符号链接(自己验证),所以将它添加到PATH中,例如:

Sys.setenv(PATH = paste("C:/cygwin64/bin/gawk", Sys.getenv("PATH"), sep = ":"))

注意:这不会永久添加,因此您必须从每个会话开始时开始,或add to your Windows path以永久识别它。

答案 1 :(得分:1)

听起来像是&#39; awk&#39;根本找不到,也许它不在你的路径中。尝试放入awk的完整路径,例如&#39;在/ usr /斌/ AWK&#39 ;.我没有使用Windows和Cygwin,所以你真正的道路肯定会有所不同。

答案 2 :(得分:0)

只需在R中完成所有操作:

c(
  "20170710-10:31:26.121;B@13.43434@1000000.0@20170710-21:15:53.23@@2017071023:59:43.158@@T@20170710-23:59:43.156#B@13.41834@4000000.0@20170710-21:15:53.23@@20170710-23:59:43.158@@T@20170710-23:59:43.156#A@13.47274@1000000.0@20170710-21:15:53.23@@20170710-23:59:43.158@@T@20170710-23:59:43.156#A@13.48874@4000000.0@20170710-21:15:53.23@@20170710-23:59:43.158@@T@20170710-23:59:43.156#",
  "20170710-23:59:43.158;B@13.43434@1000000.0@20170710-21:15:53.23@@2017071023:59:43.158@@T@20170710-23:59:43.156#B@13.41834@4000000.0@20170710-21:15:53.23@@20170710-23:59:43.158@@T@20170710-23:59:43.156#A@13.47274@1000000.0@20170710-21:15:53.23@@20170710-23:59:43.158@@T@20170710-23:59:43.156#A@13.48874@4000000.0@20170710-21:15:53.23@@20170710-23:59:43.158@@T@20170710-23:59:43.156#"
) -> log_lines

# you'd get the above with `log_lines <- readLines('filename')`

matched <- stringi::stri_match_first_regex(log_lines, "([[:digit:]]+:[[:digit:]]+:[[:digit:]]+\\.[[:digit:]]+)")[,2]

cat(
  rev(
    sprintf(
      "%s,%s\n", 
      matched, 
      lubridate::hms(matched) %>% 
        as.numeric() %>% 
        sprintf("%9.3f", .)
    )
  ),
  sep=""
)

这样做:

10:31:26.121,37886.121
23:59:43.158,86383.158

并且,您可以cat到文件或存储在数据框(等)中。

我认为awk对你来说可能比较熟悉,但使用它绝对没有意义。