【问题标题】:Append multiple header information fields to file until next header found将多个标头信息字段附加到文件,直到找到下一个标头
【发布时间】:2017-07-03 13:49:30
【问题描述】:

我正在尝试使用 bash 解析许多日志文件。日志文件如下所示:

"",1/8/2016
"Timezone",-6

"Serial No.","000001"
"Location:","LS_trap_2c"
"High temperature limit (�C)",-20
"Low temperature limit (�C)",-40
"Date - Time","Temperature (�C)"
"8/11/2015 12:00",28.0
"8/11/2015 14:00",28.5
"8/11/2015 16:00",24.0

"",1/8/2016
"Timezone",-6

"Serial No.","000002"
"Location:","LS_trap_2D"
"High temperature limit (�C)",-20
"Low temperature limit (�C)",-40
"Date - Time","Temperature (�C)"
"8/11/2015 12:00",28.0
"8/11/2015 14:00",28.5

我想将序列号和位置(以后可能还有其他)附加到每一行,直到到达下一个标题,并将其输出到master.csv 文件。该文件最终应如下所示:

"",1/8/2016
"Timezone",-6

"Serial No.","000001"
"Location:","Trap_2c"
"High temperature limit (�C)",-20
"Low temperature limit (�C)",-40
"Date - Time","Temperature (�C)"
LS_trap_2c,000001,"8/11/2015 12:00",28.0
LS_trap_2c,000001,"8/11/2015 14:00",28.5
LS_trap_2c,000001,"8/11/2015 16:00",24.0

"",1/8/2016
"Timezone",-6

"Serial No.","00002"
"Location:","LS_trap_2D"
"High temperature limit (�C)",-20
"Low temperature limit (�C)",-40
"Date - Time","Temperature (�C)"
LS_trap_2D,00002,"8/11/2015 12:00",28.0
LS_trap_2D,00002,"8/11/2015 14:00",28.5

这是一个帮助我使用 bash sed 处理类似文件的问题:

Bash Append header information to each line of a file until next header found

这个oneliner非常适合查找标题,将其存储在holdspace中并将其添加到每行的前面

sed -r '/^"/h;//!{G;s/(.*)\n.*"(.*)"/\2,\1/}' fil.csv  >masfil.csv

这种方法不适用于将多个字符串附加到前面,因为我不确定如何在 sed 中使用多个保留空间。另外,我不确定 sed 是否是最好的方法。我对 sed 不是很熟悉,所以任何指针都将不胜感激。

【问题讨论】:

    标签: linux bash csv awk sed


    【解决方案1】:

    sed 中只有一个保持空间,但在这种情况下不需要多个:

    /^"Serial No."/ {       # If we are on the "Serial No." line...
        N                   # Append next line to pattern space
        h                   # Copy pattern space to hold space
        # Remove everything but location and serial number from pattern space
        s/"[^"]*","([^"]*)"\n"[^"]*","([^"]*)"/\1,\2,/
        x                   # Swap pattern space and hold space
    }
    /^"[[:digit:]]/ {       # We are on a line where we want to prepend our data
        G                   # Append hold space to pattern space
        s/(.*)\n(.*)/\2\1/  # Move hold space content to front of pattern space
    }
    

    如果这是存储在文件sedscr.sed中,可以这样调用

    sed -E -f sedscr.sed infile
    

    确实删除了双引号,如示例输入/输出中所示;它还假设应该在数据前面添加日期的行是带有日期的行,即以双引号和数字开头。

    【讨论】:

      【解决方案2】:

      awk 来救援!

      假设您的数据是一致的

      awk -F, '/"Serial No."/ {sn = $2} 
               /"Location:"/  {loc = $2} 
               /"([0-9]{1,2}\/){2}[0-9]{4} [0-9]{2}:[0-9]{2}"/ 
                              {$0 = loc FS sn FS $0}1' file
      

      在分配 sn 和 loc 时,您也可以使用 gsub(/"/,"",$2) 去掉引号,但由于其余字段都被引用,因此不确定要删除它们。

      【讨论】:

      • 感谢您的快速回答 - 显然我的数据不一致 - 您的 awk 适用于我发布的数据,但不适用于我的真实数据(我认为它们是相同的)。序列号长度不同,位置名称也不同,但仍然......它只适用于发布的数据......你能指出一个资源来理解你给我的 awk 吗?
      • 您的 awk 有效,但仅当我将数据复制/粘贴到新文件中时。我认为这可能是由于一个/多个回车,但我不确定。
      猜你喜欢
      • 2017-07-02
      • 2012-08-19
      • 2017-03-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-28
      相关资源
      最近更新 更多