如何根据下一行中存在的模式组合当前行和下一行。 (使用awk)

时间:2013-09-27 15:53:30

标签: regex linux bash sed awk

我在这个网站上尝试了无数的awk语法建议,但不知怎的,我无法理解awk ..

我正在尝试将两行(当前的一行和下一行)组合在一起,只有当我的expr存在于下一行时。

例如,我有一个包含以下内容的文本文件:

<option value="1" selected> channel 1 
<div id="program_13" class="tree_3"><input type="checkbox" name="output_checkbox" value="13">&nbsp; &nbsp;Somename1</div>
<option value="2" selected> channel 2 
<div id="program_21" class="tree_3"><input type="checkbox" name="output_checkbox" value="21">&nbsp; &nbsp;Someothername</div>
<option value="3" selected> channel 3 
<option value="4" selected> channel 4 
<option value="5" selected> channel 5

只有当下一行中存在“output_checkbox”表达式时,我才想将当前行与下一行连接起来。对于5条主线中的任何一条或任何一条,这可能是真实的。

在上面的例子中,我想要的结果是:

<option value="1" selected> channel 1 <div id="program_13" class="tree_3"><input type="checkbox" name="output_checkbox" value="13">&nbsp; &nbsp;Somename1</div>
<option value="2" selected> channel 2 <div id="program_21" class="tree_3"><input type="checkbox" name="output_checkbox" value="21">&nbsp; &nbsp;Someothername</div>
<option value="3" selected> channel 3 
<option value="4" selected> channel 4 
<option value="5" selected> channel 5

我希望最后通过使用sed获得以下内容(我认为我可以处理):

channel 1: Somename1
channel 2: Someothername
channel 3: 
channel 4: 
channel 5:

我期待着您的建议

4 个答案:

答案 0 :(得分:3)

试试这一行:

awk '/output_checkbox/{printf "%s",$0;next}{printf (NR>1?"\n%s":"%s"), $0}END{print ""}' file

小测试:

kent$  cat f
<option value="1" selected> channel 1 
<div id="program_13" class="tree_3"><input type="checkbox" name="output_checkbox" value="13">&nbsp; &nbsp;Somename1</div>
<option value="2" selected> channel 2 
<div id="program_21" class="tree_3"><input type="checkbox" name="output_checkbox" value="21">&nbsp; &nbsp;Someothername</div>
<option value="3" selected> channel 3 
<option value="4" selected> channel 4 
<option value="5" selected> channel 5

kent$  awk '/output_checkbox/{printf "%s",$0;next}{printf (NR>1?"\n%s":"%s"), $0}END{print ""}' f 
<option value="1" selected> channel 1 <div id="program_13" class="tree_3"><input type="checkbox" name="output_checkbox" value="13">&nbsp; &nbsp;Somename1</div>
<option value="2" selected> channel 2 <div id="program_21" class="tree_3"><input type="checkbox" name="output_checkbox" value="21">&nbsp; &nbsp;Someothername</div>
<option value="3" selected> channel 3 
<option value="4" selected> channel 4 
<option value="5" selected> channel 5

答案 1 :(得分:2)

我想出了以下内容:

/output_checkbox/ { sub(/\n/, "", last); printf "%s" last; print; last = "" }

!/output_checkbox/ { printf "%s" last; last = ($0  "\n"); } 

END { printf "%s" last }

答案 2 :(得分:1)

最简单的方法是将前一行保留在变量中:

awk '/pattern/{print prev $0;prev="";next} prev{print prev} {prev=$0} END{print prev}'

正如@Kent指出的那样,问题规范存在一个模糊性:如果两个连续的行匹配/pattern/,那么需要什么(我认为这不是OP中提出的实际问题中的问题。)< / p>

我的小程序假设意图是/pattern/只有在前一行本身不匹配/pattern/时才会附加到前一行。所以它将转向:

<line>1
<pattern>2
<pattern>3

<line>1<pattern>2
<pattern>3

但还有另一种解释,其中附加了所有/pattern/行,产生:

<line>1<pattern>2<pattern>3

要获得该结果,只需进行简单修改:

awk '/pattern/{prev = prev $0; next} prev{print prev} {prev=$0} END{print prev}'

注意:这两个程序都删除了空行。

答案 3 :(得分:1)

我对Awk没有任何线索,但是如果你想要一个正常的模式,这个可以工作:

.+?(channel .+?)(?:(?:\s|\z)+?.+? &nbsp;(.+?)</div>)?

结果将是:

channel 1 Somename1
channel 2 Someothername
channel 3   
channel 4   
channel 5   

如果您想使用awk,这可以帮助您: http://www.unixcl.com/search/label/Awk