我正在尝试使用awk来解析多行表达式。其中一个看起来像这样:
_begin hello world !
_attrib0 123
_attrib1 super duper
_attrib1 yet another value
_attrib2 foo
_end
我需要提取与_begin和_attrib1相关的值。所以在这个例子中,awk脚本应该返回(每行一个):
hello world ! super duper yet another value
使用的分隔符是制表符(\ t)字符。空格仅在字符串中使用。
答案 0 :(得分:8)
以下awk脚本完成了这项工作:
#!/usr/bin/awk -f
BEGIN { FS="\t"; }
/^_begin/ { output=$2; }
$1=="_attrib1" { output=output " " $2; }
/^_end/ { print output; }
您没有指定是否要将标签(\t
)作为输出字段分隔符。如果你这样做,请告诉我,我会更新答案。 (或者你可以;这是微不足道的。)
当然,如果你想要一个可怕的选择(因为我们接近Hallowe'en),这里有一个使用sed
的解决方案:
$ sed -ne '/^_begin./{s///;h;};/^_attrib1[^0-9]/{s///;H;x;s/\n/ /;x;};/^_end/{;g;p;}' input.txt
hello world ! super duper yet another value
这是如何工作的? Mwaahahaa,我很高兴你问。
/^_begin./{s///;h;};
- 当我们看到_begin
时,将其剥离并将其余部分存储到sed的“保留缓冲区”。/^_attrib1[^0-9]/{s///;H;x;s/\n/ /;x;};
- 当我们看到_attrib1
时,将其剥离,将其附加到保持缓冲区,交换保持缓冲区和模式空间,用空格替换换行符,并交换保持缓冲区和模式空间又回来了。/^_end/{;g;p;}
- 我们已经到了最后,所以将保持缓冲区拉入模式空间并打印出来。这假设您的输入字段分隔符只是一个标签。
太简单了。谁曾说sed
是神秘的?!
答案 1 :(得分:1)
这应该有效:
#!/bin/bash
awk 'BEGIN {FS="\t"} {if ($1=="_begin" || $1=="_attrib1") { output=output " " $2 }} END{print output}'