我有一个简单的问题。我需要删除两个模式之间出现的所有情况。IE。
<INFOSTART
A=1
B=2
C=3
D=4
<INFOEND
<INFOSTART
G=1
Z=3
<INFOEND
Run Code Online (Sandbox Code Playgroud)
所以我希望输出如下
A=1 B=2 C=3 D=4
G=1 Z=3
Run Code Online (Sandbox Code Playgroud)
知道我该怎么做吗?并提前感谢大家..
您可以将简单的状态机与 一起使用awk,例如使用以下输入文件,稍微修改一下以允许标记之外的文本(如果没有这样的文本,它仍然会按需要工作,这只是为了处理额外的情况):
xyzzy
plugh
<INFOSTART
A=1
B=2
C=3
D=4
<INFOEND
twisty
passages
<INFOSTART
G=1
Z=3
<INFOEND
after
last
Run Code Online (Sandbox Code Playgroud)
对于这样的数据文件(或原始文件),以下awk命令可以满足您的需求,将开始标记和结束标记之间的行组合成一行:
awk ' /^<INFOSTART$/ {inside=1; sep=""; next}
/^<INFOEND$/ {inside=0; print ""; next}
inside {printf sep""$0; sep=" "; next}
{print}' input_file
xyzzy
plugh
A=1 B=2 C=3 D=4
twisty
passages
G=1 Z=3
after
last
Run Code Online (Sandbox Code Playgroud)
更详细地检查awk代码,以下部分对每一行进行了扩展。
每当您找到仅包含开始标记的行时,就会运行以下段。它将状态设置inside为 true(非零)以指示您应该开始组合行,并将初始分隔符设置为空字符串以确保组合行上没有前导空格。只需next立即获取下一个输入行,开始一个新的循环:
/^<INFOSTART$/ {inside=1; sep=""; next}
Run Code Online (Sandbox Code Playgroud)
假设您没有找到开始标记,则该段将针对结束标记运行。如果找到,inside状态将设置回 false(零)以开始打印出与输入文件中显示的行完全相同的行。它还输出一个换行符以正确完成组合行,然后使用下一个输入行重新开始循环:
/^<INFOEND$/ {inside=0; print ""; next}
Run Code Online (Sandbox Code Playgroud)
如果您确定该线既不是开始标记也不是结束标记,则您的行为取决于状态inside。对于 true,您需要将输入行组合成单个输出行,因此您只需打印分隔符,后跟行本身,而无需尾随换行符。然后将分隔符设置为空格,以便下一个输入行将与上一个输入行正确分隔。然后循环返回下一个输入行:
inside {printf sep""$0; sep=" "; next}
Run Code Online (Sandbox Code Playgroud)
最后,如果你到达这里,你就知道你在开始/结束部分之外,所以你只需回显该行,就像它存在于输入文件中一样:
{print}'
Run Code Online (Sandbox Code Playgroud)
如果您不想要格式良好的版本,则可以使用以下缩小版本,假设您确定唯一的<INFO...行是开始和结束标记:
awk '/^<INFOS/{a=1;b="";next}/^<INFOE/{a=0;print"";next}a{printf b$0;b=" ";next}1'
Run Code Online (Sandbox Code Playgroud)
然而,由于这可能是在脚本中而不是单行命令中,所以我自己倾向于坚持使用可读版本。
| 归档时间: |
|
| 查看次数: |
4927 次 |
| 最近记录: |