3

読んでくれてありがとう。

簡単なユーザー情報を含むプレーンテキストファイルがあります

問題は、それらのアイテムの 1 つが欠けている場合があるということです。

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 が何も見つからない場合、まったく何も生成されないため、グローバル置換への2回目のパスすら実行できないことです。

私が夢見ているのは、検索で何も見つからない場合に何を出力するかを提供する (明らかに疑似 grep) のようなものです。

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

このようなことをする方法はありますか?再度、感謝します。

4

4 に答える 4

2

ここから始めます。欠落している電子メール行を「Email: N/A」に置き換えます。

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 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 に答える
1

gensub() に GNU awk を使用する:

$ 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

gensub(/(^|\n)...) の代わりに sub(/^..) を使用してから gsub(/\n...) を使用して、任意の awk で同じことを行うことができます。

有用な場合は、不足しているフィールドを特定し、フィールドが入力で使用される順序で「不足している」ことを示し、前もってフィールドに明示的に名前を付ける必要はありません (すべてのフィールドが少なくとも 1 つのフィールドに表示されると仮定します)。レコード) は次のようになります。

$ 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 に答える