web-dev-qa-db-ja.com

一方のファイルには存在するが、もう一方のファイルには存在しないgrep行

単純なgrepと_grep -v_を実行しようとしているため、_a.txt_ではなく_b.txt_に存在する_c.txt_から行を取得します。

3ファイルの例

_a.txt_:

_a
b
c
d
e
_

_up.txt_:

_a.up
b.up
c.up
_

_dw.txt_:

_a.dw
b.dw
_

望ましい出力:

_c
_

私は以下のコードを書きましたが、grep$(sed...)を全体ではなく一度に1行として調べます。

_sed 's/.up//' /tmp/b.txt | grep -f /tmp/a.txt | grep -vf $(sed 's/.dw//' /tmp/c.txt)
_
4
Nir

ファイルがすべて並べ替えられており、プロセス置換(bashなど)を理解するシェルを使用していると仮定します。

_$ join -t . -v 1 -o 0 <( join -t . a.txt b.txt ) c.txt
c
_

または、他のシェルの場合、

_$ join -t . a.txt b.txt | join -t . -v 1 -o 0 - c.txt
c
_

これはjoinを2回使用して、ファイル間のリレーショナル結合を実行します。データはドット区切りフィールドとして解釈されます(_-t ._を使用)。

_a.txt_と_b.txt_の結合は単純であり、

_a.up
b.up
c.up
_

これらは、最初のドット区切りフィールドが両方のファイルにある2つのファイルのすべての行です。出力は、結合フィールド(abc)と、その後に続く両方のファイルの他のフィールドで構成されます(_b.txt_のみが追加のデータを持っています)。

2番目の結合は少し特別です。 _-v 1_を使用すると、2番目のファイル_c.txt_のどの行ともペアにできない最初のファイル(上記の中間結果)のエントリを確認するよう求められます。さらに、結合フィールド自体(_-o 0_)のみを表示するように要求します。 _-o_フラグがないと、結果として_c.up_が返されます。


ファイルが並べ替えられていない場合、コマンド内で出現するファイル名file<( sort file )で置き換えることができます。

3
Kusalananda

単一の高速GNU awkコマンド:

awk -F'.' \
'{
     if (ARGIND == 1) a[$1];
     else if (ARGIND == 2 && $1 in a) comm[$1];
     else if (ARGIND == 3){
         delete a;
         if ($1 in comm) delete comm[$1]
     }
 }
 END{ for (i in comm) print i }' a.txt b.txt c.txt

出力:

c

  • -F'.'-扱います.フィールド区切りとして
  • ARGIND-処理中の現在のファイルのARGV(コマンドライン引数の配列)内のインデックス
  • comm-最初の2つのファイル間のcommon項目の配列(a.txtおよびb.txt
4
RomanPerekhrest

通信

ファイルがソートされ、重複する行が削除されたと想定します。

_comm -12 a.txt <(cut -d. -f1 b.txt) | comm -23 - <(cut -d. -f1 c.txt)
_

これは、BashとGNUユーティリティを使用して、Ubuntu用に書かれていますが、うまくいけば、他のOSでも機能します。

説明

  • _comm -12_両方のファイルが共有する行を出力します(詳細については_man comm_をお読みください)
  • <(...)プロセス置換-入力ファイルの代わりにコマンドを使用します
  • _cut -d. -f1_各行で、最初のドット以降をすべて削除します
  • _comm -23_最初のファイルに固有の行を出力します
  • _-_ファイルではなく標準入力から読み取る
2
wjandrea

指定されたファイルが並べ替えられ、内部に重複がない場合は、次のように使用します。

_$ comm -12 a.txt <(sed 's/\.[^.]*$//' up.txt) | comm -23 - <(sed 's/\.[^.]*$//' dw.txt)
_

プロセス置換(<(…))を持つシェル。他のシェルについては、以下をお読みください。


この文章で説明すること:

c.txtではなくb.txtに存在するa.txtから行を取得する

集合演算に減らすことができます:

_( a intersect b ) complement c
_

ファイルに対してset操作を実行するにはいくつかの方法があります 多くはこの回答にリストされています

コマンドcommがほとんどの操作を実行できる方法が好きです。
しかし、あなたが提示するファイルは、使用するためのクリーンなセットではありません。拡張機能は消去/削除する必要があります。 sedで拡張機能を削除する一般的な方法は次のとおりです。

_$ sed 's/\.[^.]*$//' file
_

したがって、2つのクリーンファイルは次のように作成されます。

_$ sed 's/\.[^.]*$//' up.txt > up.txt.clean
$ sed 's/\.[^.]*$//' dw.txt > dw.txt.clean
_

これら2つのファイルを使用すると、ワンライナーソリューションは次のようになります。

_$ comm -12 a.txt up.txt.clean | comm -23 - dw.txt.clean
c
_

または、_( up.txt complement dw.txt) intersect a.txt_を実行します。

_$ comm -23 up.txt.clean dw.txt.clean | comm -12 - a.txt
c
_

両方のコマンドは、いくつかのシェルで元のファイルから直接実装できます。

_$ comm -12 a.txt <(sed 's/\.[^.]*$//' up.txt) | comm -23 - <(sed 's/\.[^.]*$//' dw.txt)
_

プロセス置換が利用できない場合、次のように1つのファイルのみを使用することが可能です。

_$ sed 's/\.[^.]*$//' up.txt | comm -12 a.txt - >result1.txt
$ sed 's/\.[^.]*$//' dw.txt | comm -23 result1.txt -
c
$ rm result1.txt
_
2
Isaac

grepsortuniq、およびsedを使用するのと同様の別の代替方法を次に示します。

$ sed 's/\.\(dw\|up\)//' up.txt dw.txt | grep -xFf a.txt | sort | uniq -u
c

これは、up.txtgrepへの入力ファイルとして使用し、dw.txtおよびa.txtの各ファイルの一致リストを作成することで機能します。これにより、次のような出力が生成されます。

$ sed 's/\.\(dw\|up\)//' up.txt dw.txt | grep -xFf a.txt
a
b
c
a
b

ここでの重要な詳細は、次のとおりです。

  • sedを使用して、2つのファイルup.txtdw.txtから末尾の拡張子を削除する
  • 拡張機能を削除したら、grepを使用して、a.txtから対応する一致をフィルタリングします
  • 私たちがgrepに実行するように指示するマッチングは正確です-x
  • -Fgrepa.txtのパターンを固定文字列として扱うように指示します

上記の出力を手に入れれば、これをsortを介して実行し、uniqを使用して繰り返されない行のみを取得できます。

参考文献

0
slm
$ grep -f a.txt <(cut -d '.' -f 1 up.txt) > common.txt
$ grep -vf <(cut -d '.' -f 1 dw.txt) common.txt

2つのファイル間で最初のWordを比較し、一致するWordにcommon.txtを書き込みます。 dw.txtcommon.txtを比較し、逆一致を出力します。 「c」。

0
Nisha
Perl -F\\. -lane '
   $h{@ARGV}{$F[0]}++,next if @ARGV;
   print if exists $h{2}{$_} && !exists $h{1}{$_};
' up.txt dw.txt a.txt

ハッシュ%hを作成し、トップレベルのキーを「2」と「1」として、2が最初の引数(up.txt)を参照し、1がdw.txtを参照します。指定されたデータの場合、ハッシュ構造は次のようになります(順序は異なる場合があります)。

%h = (
   1 => { a => 1, b => 1, },
   2 => { a => 1, b => 1, c => 1, },
);

見てわかるように、メインハッシュ%h内には2つのミニハッシュがあります。したがって、3番目の引数(a.txt)を読み取るときが来たら、そのレコードが(キーとして)ミニハッシュ%2に表示され、かつ、メインハッシュ%h内のミニハッシュ%1(ハッシュのハッシュまたはHoHとも呼ばれます)。

0
Rakesh Sharma

Roman's answer のバリエーションで、簡単にするために:

gawk -F. 'ARGIND==1{ seen[$1]; next } 
         ARGIND==2{ delete seen[$1]; next }
         ($1 in seen)
' fileUP fileDW fileA
  • この ARGIND==1{ seen[$1]; next }fileUPの最初の列を、seenという名前の関連付けられた配列に保持します。
  • この ARGIND==2{ delete seen[$1]; next }fileDWに存在するものを削除します。
  • この ($1 in seen)fileAにも存在する場合、残りの印刷を行います
0
αғsнιη