すべてのテキストファイルの行だけを1回以上表示

すべてのテキストファイルの行だけを1回以上表示

a.txt

cat a.txt
a
b
x
c

b.txt

cat b.txt
d
e
a
f

キュー:

SOMEMAGICK *.txt
a

尋ねる:すべての* .txtファイルの行のみを表示する方法は?

答え1

どうですか?

cat *.txt | sort | uniq -c | egrep "^ +$(ls -1 *.txt | wc -l) "

その後、発生回数を減らすために追加できます。

cat *.txt | sort | uniq -c | egrep "^ +$(ls -1 *.txt | wc -l) " | sed -re 's/^ +[0-9]+ //'

@Stephaneのコメントによると、単一のファイルに1行が複数回表示されると、上記の内容は機能しません。これを防ぐために、最初に各ファイルを並べ替えて一意化します。

for f in *.txt; do sort -u $f > $f.uniqd; done
cat *.uniqd | sort | uniq -c | egrep "^ +$(ls -1 *.uniqd | wc -l) " | sed -re 's/^ +[0-9]+ //'

今はもう行ではありませんが。 :)

答え2

awk 'FNR == 1 { FILENUM++ }
     SEEN[$0] == FILENUM - 1 { SEEN[$0] = FILENUM }
     END { for (s in SEEN) if (FILENUM == SEEN[s]) print s }' *.txt

説明する

各ファイルの最初の行を読み取るときにFILENUM読み込むときN最初のファイルFILENUMN

各行を読み取るときに見たファイルの数を数えます(ただし、以前のすべてのファイルで見た場合にのみこれを行う必要があります)。

読み取る入力がない場合は、すべてのファイルに表示されているすべての行を印刷します。

警告する:ここで公開されているいくつかのソリューションと同様に、このソリューションにも弱点があります。質問によると、入力ファイルが空の場合は、次のものが必要です。出力がまったくありません。しかし、awkはライン指向のツールなので、空のファイルを無視します。つまり、空のファイルではFNR == 1 { FILENUM++ }増やすことはできません。FILENUM

GNU awkを使用すると、次のコマンドを使用してこのエラーを修正できます。ARGIND組み込み変数

gawk 'SEEN[$0] == ARGIND - 1 { SEEN[$0] = ARGIND }
      END { for (s in SEEN) if (ARGIND == SEEN[s]) print s }' *.txt

答え3

GNU awkの使用

awk '{
      x[$0][FILENAME]
     }
     END{
      num_files=ARGC-1;
      for (b in x)
       if (length(x[b]) == num_files) 
        print b
     }' a.txt b.txt c.txt

答え4

私はより簡単なソリューションを使用することを好みますjoin

join <(sort a.txt) <(sort b.txt)

これは両方の入力ファイルで機能しますが、空白を含む行では期待どおりに機能しない可能性があり、重複した行が複数回出力されます。

2番目の問題を解決するには、

join <(sort a.txt) <(sort b.txt) | uniq

1つ目はもう少し複雑ですが、-t発生しない文字をフィールド区切り文字として使用して、flagsで少しトリックを書きました。

$ cat a.txt 
This test
foo bar
does work
$ cat b.txt 
This is a test
foo does not work
does work
$ join <(sort a.txt) <(sort b.txt) | uniq
does work work
foo bar does not work
This test is a test
$ join -t : <(sort a.txt) <(sort b.txt) | uniq
does work

関連情報