如何转换文本以使每个输出行都以块的标题开头?

如何转换文本以使每个输出行都以块的标题开头?

我需要制作一个脚本来转换以下内容:

Name = x:y
Z =  a:b.c
Z1 = a1:b1.c1
End
Name=x1:y1
Z2 = a2:b2.c2
Z3 = a3:b3.c3
Z4 = a4:b4.c4
End
Name = l:k
s = w:e.v
End

进入:

x:y Z    a:b.c
x:y Z1   a1:b1.c1
x1:y1   Z2   a2:b2.c2
x1:y1   Z3   a3:b3.c3
x1:y1   Z4   a4:b4.c4
l:k s    w:e.v

答案1

使用=可选的周围空白作为分隔符:

awk -F '[[:blank:]]*=[[:blank:]]*' '
    $1 == "Name" {name = $2; next}
    $1 != "End"  {print name, $1, $2}
' filename

例子

当查看这些awk解决方案时,可能会发现发生的事情有点令人困惑。如果您插入一些位置合适的打印语句,您可以开始以视觉方式看到发生了什么:

$ awk -F '[[:blank:]]*=[[:blank:]]*' '
      $1 == "Name" { name = $2; print "--NAME: "$2; next }; 
      $1 != "End" { print " --END: "name,$1,$2 }
' sample.txt

产生以下输出:

--NAME: x:y
 --END: x:y Z a:b.c
 --END: x:y Z1 a1:b1.c1
--NAME: x1:y1
 --END: x1:y1 Z2 a2:b2.c2
 --END: x1:y1 Z3 a3:b3.c3
 --END: x1:y1 Z4 a4:b4.c4
--NAME: l:k
 --END: l:k s w:e.v

答案2

一种使用方式

这个小sed命令可以完成这项工作:

sed -ne '
  /^Name */{
    s/^.*= *//;
    h;
    tb;
  };
  /^End/bb;
  G;
  s/^\(.*\) *= *\(.*\)\n\(.*\)$/\3\t\1\t\2/p;
  :b
  ' <sourcefile.txt 
x:y Z       a:b.c
x:y Z1      a1:b1.c1
x1:y1       Z2      a2:b2.c2
x1:y1       Z3      a3:b3.c3
x1:y1       Z4      a4:b4.c4
l:k s       w:e.v

解释:

  • 如果一行开头为姓名,下降直到=,然后将它们存储到hold space标签并跳转到标签:b
  • 如果一行开头为结尾,跳过下一步,直到标签:b
  • 在标签之前:b(如果是其他):添加hold space, 比如果该行匹配 `string,后跟任意数量的空格和等号,可能还有一些空格,第二个字符串,换行符,最后是第三个字符串,然后打印第三个字符串,后跟一个制表符,第一个字符串是一个制表符,然后是第二个字符串。

以及一种仅使用的方法

while read line ;do
    if [ ${line//=*} = "Name" ] ;then
        name=${line//*=}
    else
        [ "${line//=*}" != "$line" ] &&
            printf "%s\t%s\t%s\n" $name ${line//=}
    fi
  done <sourcefile.txt 
x:y Z       a:b.c
x:y Z1      a1:b1.c1
x1:y1       Z2      a2:b2.c2
x1:y1       Z3      a3:b3.c3
x1:y1       Z4      a4:b4.c4
l:k s       w:e.v

答案3

这是 Perl:

perl -ne 'if(/^Name\s*=\s*(.+)/){$n=$1;}else{print "$n $_" unless /^End/}' file

解释

perl -ne意味着逐行处理输入文件 ( -n),将每一行保存到变量中$_并运行作为 的参数给出的脚本-e

if(/Name\s*=\s*(.+)/){$n=$1;}:如果该行以 开头Name = <something>,则另存<something>$n.

否则,如果该行不以 开头Name,则打印 的当前值$n、名称和该行的其余部分,除非该行是End

相关内容