Я нашел другие ссылки в сообществах StackOverflow, которые были похожи, но они не дали точного ответа на мой вопрос.
У меня есть 2 файла с разным количеством строк, НО я отсортировал их оба. Мои исходные файлы состоят из сотен строк, но для устранения неполадок я сделал file1 с 12 строками, а file2 — с 5 строками. File2 — это подмножество file1. Я хочу запустить команду, которая выведет все строки, которые есть в file1, но которых нет в file2.
Я пробовал использовать команды Unix diff
, comm
но они обе выводят полное содержимое файла file1, а это не то, что мне нужно.
Вот краткий пример:
File1 File2
A B
B E
C I
E N
G O
I
L
M
N
O
X
Итак, здесь мы видим, что все, что есть в file2, есть в file1. По какой-то причине, diff
и comm
оба показали полное содержимое file1. Я предполагаю, это потому, что он делает построчное сравнение, а не ищет по всему файлу.
Есть ли другая команда Unix, которую я могу запустить и которая выведет то, что я ожидаю?
EDIT: Команды, которые я использовал, чтобы попытаться получить то, что мне было нужно, были:
а) diff файл1 файл2
Это в основном перечислило все из file1 с < перед ним, показывающим, что содержимое было из file1, и все из file2 с > перед ним. Определенно не то, что мне было нужно
б) комм -23 файл1 файл2
Это снова показало все содержимое file1, а не разницу, как я ожидал. Я также
в) комм -3 файл1 файл2
На странице справки comm говорилось, что это выведет строки в файле 1, но не в файле 2, и наоборот, но это также не показало того, что я хотел, потому что в моем примере B появляется в обоих файлах, но на разных строках. Однако вывод думает, что он есть в одном, но не в другом, и поэтому выводит его. Поэтому вывод выглядел так:
A
B
B
C
E
E
etc.
И это было не то, чего я ожидал. Я ожидал
A
C
G
L
M
X
решение1
Вы можете просто выполнить обратный grep содержимого файла b в файле A, чтобы сделать это
пример :
francois@zaphod:/tmp$
cat > A
az
ae
ar
at
ay
au
francois@zaphod:/tmp$
cat > b
ba
by
ay
at
au
francois@zaphod:/tmp$
grep -v "$(cat /tmp/b)" /tmp/A
az
ae
ar
francois@zaphod:/tmp$
здесь выводится только строка файла A, не существующая в файле b
решение2
Вывод Diff показывает, что необходимо сделать, чтобы файл X стал файлом Y.
Согласно вашему комментарию, вы могли бы использовать следующую однострочник:
cat x y | sort -u | cat y - | sort | uniq -u
Это будет
- Прочитать оба файла
- Пересортируйте их и выведите только уникальные строки (
-u
в сортировке) - Прочитайте файл (y) и объедините его с переданным выводом
- Курортный выход
-u
Используйте uniq, чтобы использовались только строки, представленные один раз ( в unique).
Этот метод основан на теории множеств. Сначала вы складываете два множества, а затем вычитаете одно из них.
решение3
Если один из файлов является текстовым файлом в формате DOS, а другой файл является текстовым файлом в формате Unix, то каждая строка будет отличаться от всех строк в другом файле, даже если буквы в строках одинаковы. Это происходит из-за дополнительного символа возврата каретки, присутствующего в конце каждой строки в одном файле, которого нет в другом файле.
Я ожидаю следующий вывод, comm -3 file1 file2
когда file1
это текстовый файл Unix, а file2
это текстовый файл DOS (это то, что у вас есть):
A
B
B
C
E
E
G
I
I
L
M
N
N
O
O
X
Я ожидаю следующий вывод, comm -3 file1 file2
когда file1
это текстовый файл DOS, а file2
это текстовый файл Unix:
A
B
B
C
E
E
G
I
I
L
M
N
N
O
O
X
Если оба файла имеют одинаковое окончание строк, т. е. оба являются текстовыми файлами DOS или оба являются текстовыми файлами Unix, я ожидаю, что вывод comm -3 file1 file2
будет следующим:
A
C
G
L
M
X
Вы можете преобразовать оба файла в текстовый формат Unix с помощью команды
dos2unix file1 file2
... при условии, что у вас dos2unix
установлена утилита.