一致する文字列を持つ行を印刷しようとしていますが、他の行には「NA」を印刷したいです

一致する文字列を持つ行を印刷しようとしていますが、他の行には「NA」を印刷したいです

次のようなファイルがあります:

Volume1  
created=Monday  
blah blah  
foo foo  
lock mode=exclusive  
ops  
layer id=1  

Volume2  
created=Tuesday  
jibber jabber  
foo foo  
ops  
layer id=2  

Volume3  
created=Wednesday  
blaaah  
foooo  
lock mode=shared  
ops  
layer id=3

私がやりたいのは、「ロック モード」で grep して、それが存在する場合はその行全体を印刷し、存在しない場合は「NA」を印刷することです。一致しない行に何か印刷する方法がわかりません。awk または sed でも同様に実行できると思います。

次のようなコードを試しています:

grep -A6 Volume | grep "lock mode" <file>

この例では、出力に次のように表示したいと思います。

lock mode=exclusive  
NA  
lock mode=shared

答え1

簡単ですperl:

perl -l -00 -ne 'print /lock mode.*/ ? $& : "NA"'
  • -l出力フィールドの区切り文字を改行に設定します
  • -00: 段落モード(レコードは段落です)
  • -ne code: 入力レコードごとにコードを実行する
  • レコードにlock modeと任意の数の非改行文字が含まれている場合は、一致したもの ( $&) を出力し、それNA以外の場合は出力します。

基本的には同じ@iruvar の awk ソリューション、しかしperl、 。

答え2

awk段落モード内

awk -v RS= '{match($0, /lock mode=[^\n]+/); 
  print RSTART? substr($0, RSTART, RLENGTH): "NA"}' file

RS=各段落を1つのレコードとして扱います。マッチの座標をlock mode=....定義済み変数とにRSTART代入しますRLENGTHRSTARTがゼロでない場合は、RSTARTとに対応する部分文字列RLENGTHが出力され、それ以外の場合は、NAが出力されます。

答え3

GNUでsed

sed -n '
    /Volume/!d
    :a
    n
    /lock mode/{
        p
        d
        }
    /^\s*$/!ba
    c\NA
    ' <file>

awk

awk '
    BEGIN{
        FS="\n"
        RS="\n\n"
    }
    /lock mode/{
        for(i=1;i<=NF;i++)
            if($i ~ /lock mode/)
                print $i
        next
    }
    {
        print "NA"
    }
    ' <file>

関連情報