例えば、サービスAでは登録されているけれどもサービスBには登録されていないユーザの一覧を得たい、という様な場合。もちろんdiff
でよしなにやることもできますが、comm
も便利です。
例えば次の様にリストがあるとします。
サービスAのユーザーリスト(users_a.txt):
1
2
3
4
5
| alice
bob
charlie
dave
oscar
|
サービスBのユーザーリスト(users_b.txt):
1
2
3
4
5
| charlie
isaac
justin
mallory
oscar
|
これらに対してcomm
を使うと次の出力が得られます:
1
2
3
4
5
6
7
8
9
| $ comm users_a.txt users_b.txt
alice
bob
charlie
dave
isaac
justin
mallory
oscar
|
TABで揃えられた列がそれぞれ左から、Aにだけ存在する行、Bにだけ存在する行、Cにだけ存在する行、となっています。これだけだと別にそれほど便利ではないんですが、comm
はそれぞれの行を非表示にする事もできます。それぞれ、非表示にしたい行を-1
-2
-3
で指定します。
Aだけに存在する行を表示する:
1
2
3
4
| $ comm -23 users_a.txt users_b.txt
alice
bob
dave
|
両方に存在する行を表示する:
1
2
3
| $ comm -12 users_a.txt users_b.txt
charlie
oscar
|
diff
だとdiff
の後にgrep
やらなんやらして必要な物を抜き出す必要があるでしょうから、これは楽ですね。
もちろん、diff
の様に他のコマンドの標準出力を取ることもできます。
例えばhttps://example.com/api/users_b.txt
が先ほどのusers_b.txtと同じ内容を返すとするとしてAだけに登録しているユーザーを取得したい場合
1
2
3
4
| $ curl -s https://example.com/api | comm -23 users_a.txt -
alice
bob
dave
|
とできますし、2つのユーザーリストを返すAPIが有ったとして、共通のユーザーを一覧にしたい場合、次の様にできます:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
| $ curl https://example1.com/users | jq .
[
{
"username": "alice"
},
{
"username": "bob"
},
{
"username": "charlie"
},
{
"username": "dave"
},
{
"username": "oscar"
}
]
$ curl https://example2.com/users | jq .
[
{
"username": "charlie"
},
{
"username": "isaac"
},
{
"username": "justin"
},
{
"username": "mallory"
},
{
"username": "oscar"
}
]
$ comm -12 \
<(curl -s https://example1.com/users | jq -r '.[].username') \
<(curl -s https://example2.com/users | jq -r '.[].username')
charlie
oscar
|
便利ですね。
なお、入力となるテキストはソートされている必要があることに注意が必要です。
以上です。