Q:

Capturing missing host names from a file separated by comma

I have a file1.txt and file2.txt which have few hostnames separated by comma ",". I have a working solution where I loop through the value of file2.txt and capture the values which are not in file1.txt. However, when I try to execute the same through the pipeline its not working.
Can anyone advice if by using Awk or Sed or any one-liner command to achieve the same?
file1.txt
host1,host2,host3,host4,host100
file2.txt
host2,host4
expected output:
output.txt
host1,host3,host100
Thanks

A:

Assuming file2.txt looks like this:
host2,host4

You could use diff and process substitution. I replace , with newline (\n) and sort the result for both files and give the result to diff:
diff <(tr , '\n' < file1.txt | sort) <(tr , '\n' < file2.txt | sort)

Output:
1,2d0
< host1
< host100
4d1
< host3

Lines starting with < are unique to file1.txt and lines starting with > are unique to file2.txt.

A:

Similar to Ted's answer by using process substitution
# See modification below for a better approach
grep -vf <(tr , \\n < file2.txt) <(tr , \\n < file1.txt) | awk '{printf("%s%s",NR==1?"":",",$0)}'

The grep part outputs all hostnames in file1.txt but not in file2.txt, and the awk part merges all results into one line.
Also, this assumes that there's no .txt in file2.txt.

Edit: Thanks for karakfa's comment, a better approach may be
grep -xvf <(tr , \\n < file2.txt) <(tr , \\n < file1.txt) | paste -sd,

The -x option is set to match full pattern (in case there's any blank).

A:

Another take. This one splits the files on commas, sorts them, and then uses comm to get just the entries in the first file, and stores them in an array. Then prints the elements out separated by commas to the output file.
#!/usr/bin/env bash
mapfile -t hosts < <(comm -23 <(tr , "\n" < file1.txt | sort) \
                              <(tr , "\n" < file2.txt | sort))
IFS=,
echo "${hosts[*]}" > output.txt

Or using grep instead of comm:
mapfile -t hosts < <(grep -Fvf <(tr , "\n" < file2.txt) <(tr , "\n" < file1.txt))

