Linux SED - 保留空间 - 所有行的一个价值

时间:2016-04-02 15:16:29

标签: linux bash text sed sh

我想使用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。我试过了,但我不知道这应该如何工作。

谢谢!

4 个答案:

答案 0 :(得分:0)

试试这个。

#!/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);
  }
}

答案 1 :(得分:0)

您尝试使用错误的工具。虽然你可以,我想,想出一些神奇的符文来强制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

答案 2 :(得分:0)

这可能适合你(GNU sed):

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

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

答案 3 :(得分:0)

我不经常使用保持缓冲区,所以我想为练习提供一个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/
}