【问题标题】:Removing a delimited block of lines when one of them matches a regex pattern with awk当其中一个与带有 awk 的正则表达式模式匹配时,删除分隔的行块
【发布时间】:2020-12-30 22:22:07
【问题描述】:

让我们假设以下 reprepro 分发文件:

Origin: git.sdxlive.com/git/PPA
Label: Ubuntu focal
Suite: focal
Version: 20.04
Codename: focal
Architectures: i386 amd64
Components: stable unstable
Limit: 0
Description: Latest Ubuntu focal 20.04 packages
Contents: .gz .bz2
Tracking: keep
SignWith: xxxxxxxxxxxxxxxxxxxx
Signed-By: xxxxxxxxxxxxxxxxxxxx
ValidFor: 2y 6m
Log: packages.Ubuntu.log

Origin: git.sdxlive.com/git/PPA
Label: Ubuntu groovy
Suite: groovy
Version: 20.10
Codename: groovy
Architectures: i386 amd64
Components: stable unstable
Limit: 0
Description: Latest Ubuntu groovy 20.10 packages
Contents: .gz .bz2
Tracking: keep
SignWith: xxxxxxxxxxxxxxxxxxxx
Signed-By: xxxxxxxxxxxxxxxxxxxx
ValidFor: 2y 6m
Log: packages.Ubuntu.log

目标是删除由 'Origin: ' 分隔的整个行块,并在其中包含行 "Codename: ${os_code_name}" 时删除一个空行,其中 os_code_name 是一个 bash 变量。

所以预期的输出是:

Origin: git.sdxlive.com/git/PPA
Label: Ubuntu groovy
Suite: groovy
Version: 20.10
Codename: groovy
Architectures: i386 amd64
Components: stable unstable
Limit: 0
Description: Latest Ubuntu groovy 20.10 packages
Contents: .gz .bz2
Tracking: keep
SignWith: xxxxxxxxxxxxxxxxxxxx
Signed-By: xxxxxxxxxxxxxxxxxxxx
ValidFor: 2y 6m
Log: packages.Ubuntu.log

如果没有变量代号,我们可以使用例如以下内容来删除与焦点代号匹配的块:

awk '/^Origin: /{s=x} {s=s $0 RS} /^$/{if(s!~/Codename: focal/) printf "%s",s}' distributions

我找不到使用变量代号的解决方案;我尝试使用:

  1. --assign=var="${os_code_name}"
  2. ENVIRON["os_code_name"]

在第一种情况下,我不知道 awk 如何区分字符串 'Codename:' 和变量 var,因为我们不能使用“$var”。以下显然不起作用:

awk --assign=var="${os_code_name}" '/^Origin: /{s=x} {s=s $0 RS} /^$/{if(s!~/Codename: $var/) printf "%s",s}' distributions

第二种情况,同样不成功:

awk '/^Origin: /{s=x} {s=s $0 RS} /^$/{if(s!~/Codename: ENVIRON["os_code_name"]/) printf "%s",s}' distributions

我还检查了this answer

有什么建议吗?

【问题讨论】:

  • 很高兴你以代码的形式展示了你的努力,继续努力。您能否在您的问题中发布预期输出示例,然后让我们知道以更清楚

标签: bash variables awk


【解决方案1】:

您可以使用空RS,这是段落模式,并且不打印任何存在该代号的记录。

awk -v cn="$cn" -v RS="" '!($0 ~ "Codename: " cn){print $0,"\n"}' file

变量必须以链接答案所说的方式传递。模式匹配可以使用~ /.../~ "..." 来完成,这里必须使用双引号,"Codename: " var 是匹配字符串。

【讨论】:

  • 我喜欢它的简单性,但分隔线已被吞掉,这意味着这是一个问题:如果有第三个块,输出只显示一个块,在剩下的 2 个之间不再有任何空的分隔线块。
  • 出于这个原因,我已经添加了一个打印语句,还用更多块进行了测试。
【解决方案2】:

您能否尝试使用所示示例进行跟踪、编写和测试,并且应该适用于各种awk

os_code_name="focal" ##shell variable
awk -v co="$os_code_name" '
/Origin/{
  if(!foundCo && FNR>1){ print val }
  val=foundCo=""
}
/^Codename/ && $NF==co{
  foundCo=1
}
{
  val=(val?val ORS:"")$0
}
END{
  if(!foundCo){ print val }
}
'  Input_file

说明:为上述添加详细说明。

os_code_name="focal"                     ##This is a shell variable.
awk -v co="$os_code_name" '              ##Starting awk program from here and setting co variable as value of os_code_name here.
/Origin/{                                ##Checking condition if line has Origin string in it then do following.
  if(!foundCo && FNR>1){ print val }     ##Checking condition if foundCo is NULL and FNR>1 then print val here.
  val=foundCo=""                         ##Nullifying variables here.
}
/^Codename/ && $NF==co{                  ##Checking condition if line starts with Codenam and last field is equal to variable.
  foundCo=1                              ##Setting value for foundCo here.
}
{
  val=(val?val ORS:"")$0                 ##Creating val which has all lines values from Origin to just before next occurrence of Origin it either gets printed above or gets NULL.
}
END{                                     ##Starting END block of this awk program from here.
  if(!foundCo){ print val }              ##Checking condition if foundCo is NULL then print val here.
}
'  Input_file                            ##Mentioning Input_file name here.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-11-13
    • 2014-09-15
    • 2020-05-15
    • 2015-07-16
    • 2016-11-18
    • 2019-07-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多