使用 awk 删除没有后续内容行的 header 行
deleting header lines with no following content lines using awk
我想我已经做过几次了,但今天早上我做不到。
例如,我有一个这样的文件。 (这是使用foreach和diff比较多个文件的结果,文件名用###模式括起来)
<< file gg >>
### ./translations/qt_fr.ts ###
### ./translations/qt_es.ts ###
### ./translations/qt_help_hu.ts ###
### ./transla file 1 _help_hu.ts ###
< alala0
------
> blabla0
### ./translations/qt_help_hu.ts ###
### ./translations/qt_help_hu.ts ###
### ./translations/qt_help_hu.ts ###
### ./translations/qt_help_hu.ts ###
### ./translations/qt_help_hu.ts ###
### ./transl file 2 t_help_hu.ts ###
< alala0
< alala1
--------
> blabla0
> blabla1
### ./translations/qt_help_hu.ts ###
### ./translations/qt_help_hu.ts ###
### ./translations/qt_help_hu.ts ###
### ./translations/qt_help_hu.ts ###
### ./translations/qt_help_hu.ts ###
我想要做的是删除那些只有文件名的行以产生如下所示的输出。
(expected output)
### ./transla file 1 _help_hu.ts ###
< alala0
------
> blabla0
### ./transl file 2 t_help_hu.ts ###
< alala0
< alala1
--------
> blabla0
> blabla1
我怎样才能用 awk 做到这一点?我试过这个(我试着让它看起来像 C,一样)。我用 ### 'header' 行调用该行。逻辑是:我打印所有 non-header 行,但如果前一行是 header,则打印前一行。为此,我在 'kept' 变量中保留了任何 header 行。
<< file tt.awk >>
{if ([=13=] !~ /^###/)
if (flag == 1) {print $kept; print [=13=];}
else {print [=13=]}
}
{if ([=13=] ~ /^###/)
flag = 1;
else
flag = 0;
kept = [=13=];
}
当我运行awk -f tt.awk gg
时,我得到了这个结果。 'kept' 不是来自上一行而是来自当前行。 awk代码有什么问题? long-time awk 用户,我可能遗漏了一些重要的东西。
< alala0
< alala0
------
> blabla0
< alala0
< alala0
< alala1
--------
> blabla0
> blabla1
你想要的更简单:
{
if ([=10=] ~ /^###/)
{ kept = [=10=]; flag=1; }
else if (flag == 1) {print kept; print [=10=]; flag=0}
else {print [=10=]}
}
要使现有代码正常工作,请替换:
if (flag == 1) {print $kept; print [=10=];}
与:
if (flag == 1) {print kept; print [=11=];}
其他方法
$ awk '/^###/{kept=[=12=];f=1;next} f {print kept} {f=0;print}' gg
### ./transla file 1 _help_hu.ts ###
< alala0
------
> blabla0
### ./transl file 2 t_help_hu.ts ###
< alala0
< alala1
--------
> blabla0
> blabla1
为简单起见,标志f
可以去掉:
$ awk '/^###/{kept=[=13=];next} kept {print kept} {kept="";print}' gg
### ./transla file 1 _help_hu.ts ###
< alala0
------
> blabla0
### ./transl file 2 t_help_hu.ts ###
< alala0
< alala1
--------
> blabla0
> blabla1
使用 sed 方法
sed '/^###.*###/d' file
找到所有有模式的行并删除
或
sed -n '/^###.*###/!p' file
找到所有没有模式 ### 的行并打印
我想我已经做过几次了,但今天早上我做不到。 例如,我有一个这样的文件。 (这是使用foreach和diff比较多个文件的结果,文件名用###模式括起来)
<< file gg >>
### ./translations/qt_fr.ts ###
### ./translations/qt_es.ts ###
### ./translations/qt_help_hu.ts ###
### ./transla file 1 _help_hu.ts ###
< alala0
------
> blabla0
### ./translations/qt_help_hu.ts ###
### ./translations/qt_help_hu.ts ###
### ./translations/qt_help_hu.ts ###
### ./translations/qt_help_hu.ts ###
### ./translations/qt_help_hu.ts ###
### ./transl file 2 t_help_hu.ts ###
< alala0
< alala1
--------
> blabla0
> blabla1
### ./translations/qt_help_hu.ts ###
### ./translations/qt_help_hu.ts ###
### ./translations/qt_help_hu.ts ###
### ./translations/qt_help_hu.ts ###
### ./translations/qt_help_hu.ts ###
我想要做的是删除那些只有文件名的行以产生如下所示的输出。
(expected output)
### ./transla file 1 _help_hu.ts ###
< alala0
------
> blabla0
### ./transl file 2 t_help_hu.ts ###
< alala0
< alala1
--------
> blabla0
> blabla1
我怎样才能用 awk 做到这一点?我试过这个(我试着让它看起来像 C,一样)。我用 ### 'header' 行调用该行。逻辑是:我打印所有 non-header 行,但如果前一行是 header,则打印前一行。为此,我在 'kept' 变量中保留了任何 header 行。
<< file tt.awk >>
{if ([=13=] !~ /^###/)
if (flag == 1) {print $kept; print [=13=];}
else {print [=13=]}
}
{if ([=13=] ~ /^###/)
flag = 1;
else
flag = 0;
kept = [=13=];
}
当我运行awk -f tt.awk gg
时,我得到了这个结果。 'kept' 不是来自上一行而是来自当前行。 awk代码有什么问题? long-time awk 用户,我可能遗漏了一些重要的东西。
< alala0
< alala0
------
> blabla0
< alala0
< alala0
< alala1
--------
> blabla0
> blabla1
你想要的更简单:
{
if ([=10=] ~ /^###/)
{ kept = [=10=]; flag=1; }
else if (flag == 1) {print kept; print [=10=]; flag=0}
else {print [=10=]}
}
要使现有代码正常工作,请替换:
if (flag == 1) {print $kept; print [=10=];}
与:
if (flag == 1) {print kept; print [=11=];}
其他方法
$ awk '/^###/{kept=[=12=];f=1;next} f {print kept} {f=0;print}' gg
### ./transla file 1 _help_hu.ts ###
< alala0
------
> blabla0
### ./transl file 2 t_help_hu.ts ###
< alala0
< alala1
--------
> blabla0
> blabla1
为简单起见,标志f
可以去掉:
$ awk '/^###/{kept=[=13=];next} kept {print kept} {kept="";print}' gg
### ./transla file 1 _help_hu.ts ###
< alala0
------
> blabla0
### ./transl file 2 t_help_hu.ts ###
< alala0
< alala1
--------
> blabla0
> blabla1
使用 sed 方法
sed '/^###.*###/d' file
找到所有有模式的行并删除 或
sed -n '/^###.*###/!p' file
找到所有没有模式 ### 的行并打印