AWKまたはSEDを使用して他のファイルから変数を削除してファイルの行を削除する

AWKまたはSEDを使用して他のファイルから変数を削除してファイルの行を削除する

data.txtファイルの2番目の列パラメータの1つを含むすべての行を削除したいですkeys.txt

  • keys.txt
    2 aa
    2 bb
    2 cc
    2 dd
    
  • data.txt
    1 aa It is great
    1 aa I want to delete this line
    1 kk Really ?
    1 bb Yes, I think so.
    1 bb Why ?
    1 kk Because I don't like the current situation
    1 ll I want to change
    1 cc Indeed it's a need
    1 cc Sorry
    1 zz Ok !
    
  • 希望の出力
    1 kk Really ?
    1 kk Because I don't like the current situation
    1 ll I want to change
    1 zz Ok !
    

次のプログラムを試してみましたawk

awk '
    NR == FNR {pattern[$0]; next}
    {
        for (var in pattern) {
            if ($0 ~ var) {
                getline
                next
            }
        }
        print >> GoodFile.txt
    }
' keys.txt

答え1

あなたはかなり近かったが、いくつかの小さな点が欠けている。

  • data.txtこれを呼び出しにパラメータとして追加する必要がありますawk。それ以外の場合、ファイルは処理されません。
  • 現在、行全体をkeys.txt削除データベースに登録しているので、2番目のフィールド($2代わりに$0)に制限する必要があります。
  • if ($0 ~ var)行を除外する必要があるかどうかを確認するために使用されます。data.txtここでも行の2番目のフィールドのみを比較する必要があり、キーに==正規表現関連文字を含めることができないようにするには、正規表現一致ではなく完全一致()を使用する必要があります。
  • から印刷しawkますが、必ずしもそうする必要はありません。代わりに出力をリダイレクトできます。

したがって、少し変更すると、次のようになります。

awk 'NR==FNR{pattern[$2];next} !($2 in pattern)' keys.txt data.txt > GoodFile.txt

keys.txtこれは配列の各行の2番目の列を登録しますpatternが、ファイルに対して他の操作は実行しません。なぜなら、data.txt各行について条件が評価される点に達するからです。!($2 in pattern)条件が「true」と評価される場合(つまり、行の2番目の列いいえ配列のインデックスからpattern)現在の行が印刷されます。

答え2

スクリプトの最初の質問は次のとおりです。

NR == FNR {pattern[$0]; next}

行全体を配列のキーとして使用しますpatternが、2番目のフィールドのみが必要です。と両方を使用する必要nextはなく、単に次の行に進んでgetlineください。nextまた、2番目のファイルを入力として渡すことを忘れました。最後に、ファイル名は変数ではなく文字列なので、引用符で囲む必要があります。これら2つのエラーを修正すると、次のようになります。

awk '
    NR == FNR {pattern[$2]; next}
    {
        for (var in pattern) {
            if ($0 ~ var) {
                getline
                next
            }
        }
        print >> "GoodFile.txt"
    }
' keys.txt data.txt

今あなたは確かにそこでそれをしたいですか>>?これはawk、ファイルにすでに存在する項目(以前の実行の出力など)を上書きしないことを意味します。シングルランの出力を上書きしたくない場合は>>不要です。これは、前の実行のデータを保持したい場合にのみ必要ですが、そうではありません。awk>>>

また、データに基づいて実際に行全体を確認したくありません。data.txt2番目のフィールドがの2番目のフィールドと同じ行だけをスキップしようとしていますkeys.txt。そうであれば、特に大容量ファイルの場合、より効率的です。

awk '
    NR == FNR {pattern[$2]; next}
    {
        if ($2 in pattern) {
            next
        }
        print > "GoodFile.txt"
    }
' keys.txt data.txt

または同等ですが、より簡潔に言えば、

awk '
    NR == FNR {pattern[$2]; next}
    {
        if (!($2 in pattern) {
            print > "GoodFile.txt"
        }
    }
' keys.txt data.txt

答え3

GNU sed拡張正規表現モードオン-E、自動印刷モード空白オフ-n

$ sed -En '
    /^\S+\s+(\S+)$/{
      s//\1/;H;d
    }
    G
    /^\S+\s+(\S+)\s.*\n\1(\n|$)/!P
' keys.txt data.txt

キーファイルに 2 つのフィールドがあり、データファイルに 2 つ以上のフィールドがあるとします。

最初のステップでは、key.txtファイルの2番目のフィールドを保留状態に保存します。次に、data.txt ファイルの読み込み中に、data.txt ファイルの現在のレコードにキーを追加し、データの 2 番目のフィールドがキーのどこに表示されるかを比較します。見つからない場合にのみデータを印刷します。

関連情報