3

谢谢阅读。

我有一个包含一些简单用户信息的纯文本文件

问题是,有时其中一件物品会丢失。

请注意 Norman 和 Reggie 如何显示电子邮件地址,但 Missy 没有:

Name: Norman Normalrecord
Email: norman@ooga.com
Addr: 123 Main street

Name: Missy Missington
Addr: 789 Back street

Name: Reggie Regularrecord
Email: reggie@booga.com
Addr: 456 Middle street

我想 grep / sed 并说“如果找不到电子邮件地址,请用文本 missing_email_addr 替换”,所以我得到了这个结果:

Norman Normalrecord
norman@ooga.com
123 main street

Missy Missington
MISSING_EMAIL_ADDR
789 back street

Reggie Regularrecord
reggie@booga.com
456 middle street

问题是,在我所有的实验中,当什么都没有找到时,grep / sed 绝对不会产生任何东西,所以我什至不能第二次通过 global-replace。

我梦想的是(显然是伪grep),当搜索没有找到任何东西时提供打印的内容:

grep /Name:/MISSING_NAME/email:/MISSING_EMAIL_ADDR/Addr:/MISSING_STREET_ADDR/

有没有办法做这样的事情?再次感谢。

4

4 回答 4

2

这是一个开始。它将丢失的电子邮件行替换为“电子邮件:不适用”。

awk -v RS='\n\n' -v FS='\n' -v OFS='\n' \
    '{ if (!$3) $3 = "Email: N/A"; print; print "" }' users.txt

输出:

Name: Norman Normalrecord
Email: norman@ooga.com
Addr: 123 Main street

Name: Missy Missington
Addr: 789 Back street
Email: N/A

Name: Reggie Regularrecord
Email: reggie@booga.com
Addr: 456 Middle street
于 2013-04-12T18:45:40.447 回答
1

将 GNU awk 用于 gensub():

$ cat tst.awk
BEGIN { RS=""; ORS="\n\n"; FS=OFS="\n" }
NF<3  { $3=$2; $2="Email: MISSING_EMAIL_ADDR" }
{ print gensub(/(^|\n)[^:]+:[[:space:]]*/,"\\1","g") }

$ gawk -f tst.awk file
Norman Normalrecord
norman@ooga.com
123 Main street

Missy Missington
MISSING_EMAIL_ADDR
789 Back street

Reggie Regularrecord
reggie@booga.com
456 Middle street

您可以在任何 awk 中使用 sub(/^..) 然后 gsub(/\n...) 而不是 gensub(/(^|\n)...) 来执行相同的操作。

如果有用,请识别任何缺失的字段并按照字段在输入中使用的顺序为其提供“缺失”指示,而无需预先明确命名任何字段(假设每个字段至少出现在一个记录)将是:

$ cat tst.awk
BEGIN { RS=""; FS=OFS="\n" }
{
   for (fldNr=1; fldNr<=NF; fldNr++) {

      split($fldNr,nameVal,/:[[:space:]]*/)

      name = nameVal[1]
      val  = nameVal[2]

      rec[NR,name] = val

      if (!seen[name]++) {
         for (nameNr=++numNames; nameNr>fldNr; nameNr--) {
            names[nameNr] = names[nameNr-1]
         }
         names[nameNr] = name
      }

   }

}

END {
   for (recNr=1; recNr<=NR; recNr++) {

      for (nameNr=1; nameNr<=numNames; nameNr++) {

         name = names[nameNr]
         key  = recNr SUBSEP name

         if (key in rec) {
            print rec[key]
         }
         else {
            print "MISSING_" toupper(name)
         }
      }

      print ""

   }
}
$
$ cat file
Name: Norman Normalrecord
Email: norman@ooga.com
Addr: 123 Main street

Name: Missy Missington
Addr: 789 Back street

Name: Reggie Regularrecord
Email: reggie@booga.com
Addr: 456 Middle street
Whatever: Some useful info
$
$ awk -f tst.awk file
Norman Normalrecord
norman@ooga.com
123 Main street
MISSING_WHATEVER

Missy Missington
MISSING_EMAIL
789 Back street
MISSING_WHATEVER

Reggie Regularrecord
reggie@booga.com
456 Middle street
Some useful info
于 2013-04-14T11:13:52.200 回答
1

这可能对您有用(GNU sed):

sed '/^Name: /!b;:a;$!N;/\nAddr: /!ba;/\nEmail: /!s/\n/&Email: MISSING_EMAIL_ADDR&/' file

如果要删除标签:

sed -r '/^Name: /!b;:a;$!N;/\nAddr: /!ba;/\nEmail: /!s/\n/&Email: MISSING_EMAIL_ADDR&/;s/(Name|Email|Addr): //g' file
于 2013-04-13T01:05:25.440 回答
0

这是一个sed似乎可以实现您“梦想”的脚本(它假设条目用空行分隔):

$ cat s.sed
# collect the lines from one entry in the pattern space
# removing the empty line for consistency
:a; $!{N;/\n$/!ba}; s/\n$// 
# make substitutions
/Name:/!s/^/MISSING_NAME\n/
/Email:/!s/\n/\nMISSING_EMAIL_ADDR\n/
/Addr:/!s/$/\nMISSING_STREET_ADDR/
# add an empty line back
s/$/\n/p

使用您的数据:

$ sed -nf s.sed info.txt 
Name: Norman Normalrecord
Email: norman@ooga.com
Addr: 123 Main street

Name: Missy Missington
MISSING_EMAIL_ADDR
Addr: 789 Back street

Name: Reggie Regularrecord
Email: reggie@booga.com
Addr: 456 Middle street

另一个演示:

$ cat info_ext.txt 
Email: norman@ooga.com
Addr: 123 Main street

Name: Missy Missington
Addr: 789 Back street

Name: Reggie Regularrecord
Email: reggie@booga.com

$ sed -nf s.sed info_ext.txt 
MISSING_NAME
Email: norman@ooga.com
Addr: 123 Main street

Name: Missy Missington
MISSING_EMAIL_ADDR
Addr: 789 Back street

Name: Reggie Regularrecord
Email: reggie@booga.com
MISSING_STREET_ADDR
于 2013-04-12T19:29:20.493 回答