【问题标题】:Linux SED - Hold Space - One Value to all LinesLinux SED - 保留空间 - 所有行的一个值
【发布时间】:2016-07-22 08:43:15
【问题描述】:

我想使用 sed 转换文件。源文件具有以下格式('deviceId' 是占位符):

CREATE DATABASE "deviceId";
column value=88i 1445137680000000000 
column value=68i 1445137620000000000
column value=80i 1445137560000000000
column value=39i 1445137500000000000

转换后,格式如下:

USE DATABASE "db";
series,device=deviceId column=88i 1445137680000000000 
series,device=deviceId column=68i 1445137620000000000
series,device=deviceId column=80i 1445137560000000000
series,device=deviceId column=39i 1445137500000000000

但我不明白,如何在每一行中获取 deviceId。我当前的sed.txt 包含以下代码:

s/^\(CREATE DATABASE ".*";\)$/USE DATABASE "db";/g
s/\(.*\) .*=\(.*\) \(.*\)/series,device= \1=\2 \3/g

并生成以下输出:

USE DATABASE "db";
series,device= column=88i 1445137680000000000·
series,device= column=68i 1445137620000000000
series,device= column=80i 1445137560000000000
series,device= column=39i 1445137500000000000

有人可以解释我如何在每一行中获取 deviceId 吗?我已经看到了使用 Hold-Space/Flow-Work 的可能性。我已经尝试过了,但我不明白这应该如何工作。

谢谢!

【问题讨论】:

  • 需要sed吗?

标签: linux bash text sed sh


【解决方案1】:

试试这个。

#!/usr/bin/perl
use strict;
use warnings;
my $deviceId = ""; 
while( my $line = <STDIN>) {
  chomp($line);
  if($line =~ m/CREATE DATABASE/) {
    $deviceId = $line;
    $deviceId =~ s/CREATE DATABASE "(.*)"/$1/;
    print('USE DATABASE "db";' . "\n");
  }
  else {
    $line =~ s/(.*) .*=(.*) (.*)/series,device=$deviceId $1=$2 $3\n/g;
    print($line);
  }
}

【讨论】:

  • 谢谢,但这不是我需要的。 \3 只是当前行的时间戳。我需要的是第一行的 deviceId。
【解决方案2】:

您尝试使用错误的工具。虽然你可以,我希望,想出一些神奇的符文来强制 sed 产生你想要的输出,为了健壮性、可移植性、简单性、效率和几乎所有其他理想的软件属性,标准的 UNIX 工具用于任何其他比单独行上的简单替换是 awk:

$ awk -F'["=]' '
    NR==1{dev=$(NF-1); $0 = "USE DATABASE \"db\""}
    NR>1 {$0 = "series,device=" dev " column=" $2}
1' file
USE DATABASE "db"
series,device=deviceId column=88i 1445137680000000000
series,device=deviceId column=68i 1445137620000000000
series,device=deviceId column=80i 1445137560000000000
series,device=deviceId column=39i 1445137500000000000

【讨论】:

    【解决方案3】:

    这可能对你有用(GNU sed):

    sed -re '1h;1cUSE DATABASE "db";' -e 'G;s/.*value(.*)\n.*"(.*)".*/series,device=\2 column\1/' file
    

    这会将第一行存储在保持空间 (HS) 中。将第一行更改为所需的格式。然后在第一行之后的每一行:附加存储的第一行并使用模式匹配和反向引用将该行按摩为所需的格式。

    【讨论】:

      【解决方案4】:

      我不经常使用保持缓冲区,所以我想提供一个 sed 解决方案来练习:

      /^CREATE/ {
          # strip everything surrounding deviceId
          s/[^"]*"\([^"]*\).*/\1/
      
          # copy to the hold buffer
          h
      
          # replace pattern buffer with USE ...
          s/.*/USE DATABASE "db";/
      }
      
      /^column/ {
          # append the hold space to the pattern buffer
          # this adds a leading newline which we'll use to capture deviceId
          G
      
          # capture the 1st field, value of the 2nd, the 3rd field,
          # then the appended deviceId after the newline
          s/\([^ ]*\) .*=\([^ ]*\) \(.*\)\n\(.*\)/series,device=\4 \1=\2 \3/
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-01-03
        • 2015-04-26
        • 2021-07-19
        • 2018-11-02
        • 1970-01-01
        • 1970-01-01
        • 2014-02-04
        相关资源
        最近更新 更多