2

我已经在这个站点上尝试了无数关于 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

4 回答 4

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
于 2013-09-27T16:00:22.503 回答
2

我想出了以下内容:

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

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

END { printf "%s" last }
于 2013-09-27T16:19:57.670 回答
1

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

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

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

我的小程序假定/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}'

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

于 2013-09-27T16:01:14.733 回答
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

于 2013-09-27T16:48:15.993 回答