Я должен сравнить содержание текстовых файлов (в целом и не мудрый строкой как различная команда) и распечатать недостающий текст. Существует ли команда, чтобы сделать так?Заранее спасибо.
Править: Как пример, скажите, что file1 имеет:
1 2 3
4 5
файл 2 имеет:
1 5
2 3 4 6
Я хочу сравнить эти файлы и печать, как произведено:
6
Команда diff
сравнивает текстовые файлы линию за линией, в этом случае, почти весь файл будет распечатан. (Мои фактические файлы более сложны и длинны, таким образом, я даю простой пример.)
Другое решение (python):
def readFile(fi):
return open(fi,"rb").read().decode(cod)
def process(text):
return text.replace("\n"," ").split(" ")
print(set([x for x in process(readFile(file1,"utf-8")) if not x==""]).difference(set([x for x in process(readFile(file2,"utf-8")) if not x==""])))
Я приму следующее: Ваши файлы состоят из данных, которые или разделяются с пространством или новой строкой, И Вы не заботитесь о знании, где данные отсутствуют (или знайте, что это всегда, например, в file2).
то, Что мы сделаем, просто: Замените каждое пространство новой строкой в обоих файлах, свяжите их, затем ищите единственные (уникальные) записи только:
sort <( tr ' ' '\n' < file1 ) <(tr ' ' '\n' < file2) | uniq -u
Так как порядок не имеет значения, можно использовать awk для печати уникальных строк, но с пробельными строками разделения:
awk -v RS='[[:space:]]+' 'FNR==NR {a[$0]++; next} {a[$0]--} END {for (i in a) if (a[i] != 0) print i}' file1 file2
Здесь:
-v RS='[[:space:]]+'
устанавливает разделитель записей (RS) на любой пробел, таким образом, вся каждая "строка" будет разделена любым пробелом (включая новые строки).FNR == NR
- FNR
рекордное число (NR
) (или, номер строки, если Вы будете) для текущего файла, и NR
полный номер строки во всех входных файлах. Так, каждый раз, когда эти два равны, мы имеем дело с первым файлом.{a[$0]++; next}
- набор и инкремент количество появлений текущей "строки", затем переместитесь в следующую строку, не обрабатывая, больше управляет. Этот блок только выполняется для первого файла, таким образом, эффект состоит в том, что это правило относится к строкам из первого файла, и следующий блок относится всем другим файлам.{a[$0]--}
, постепенно уменьшите количество появлений текущей "строки".END {for (i in a) if (a[i] != 0) print i}
- в конце всего входа, для каждой записи в массиве a
, распечатайте ту запись, если количество появлений не 0. Так, любая "строка", которая была замечена равное количество раз в обоих файлах, будет пропущена.Это - другое решение:
comm -3 <( cat file1 | tr ' \t' '\n' | sort) <(cat file2 | tr ' \t' '\n' | sort) | sort -u
где:
tr ' \t' '\n' | sort
замените пространство и вкладку с новой строкой, и переупорядочьте результатcomm
Сравнивает отсортированные файлы file1
и file2
линию за линией, и с -3
опция подавляет строки, которые появляются в обоих файлахsort -u
наконец, удаляет дублирующиеся строки, это необходимо в случае дублирующегося маркераВ этом случае tr ' ' '\n' | sort
вывод используется в качестве стандартного входа для comm
команда.
Если я понимаю правильно, Вы хотите распечатать уникальные числа или слова в сравнении. Я преобразовал бы файлы так, чтобы каждое число/слово имело собственную строку, отсортируйте их, удалите пустые строки и дубликаты и после этого сравните файлы.
Я предполагаю, что пробелы разделяют числа или слова. Для каждого файла
< file-x.orig tr ' ' '\n' | tr -s '\n' '\n' |sort -u > file-x.1
Посмотрите man tr
для деталей.
Если Вы хотите отсортировать численно, можно добавить опцию -n
или -h
в зависимости от числового формата. Посмотрите man sort
для деталей.
В примере исходного вопроса я использовал бы -n
,
< file-x.orig tr ' ' '\n' | tr -s '\n' '\n' |sort -nu > file-x.1
где x может быть a и b для этих двух файлов для сравнения, так например,
< file-a.orig tr ' ' '\n' | tr -s '\n' '\n' |sort -nu > file-a.1
< file-b.orig tr ' ' '\n' | tr -s '\n' '\n' |sort -nu > file-b.1
Можно осмотреть эти преобразованные и отсортированные файлы, если Вы желаете.
Наконец сравните файлы со следующей командной строкой,
$ diff file-a.1 file-b.1
5a6
> 6
Это определяет число, которое только найдено во втором файле Вашего демонстрационного входа от исходного вопроса. Посмотрите man diff
для получения дополнительной информации если Вы хотите измененный вывод от diff
.
Это - пример с уникальным числом в каждом из файлов.
$ echo '1 2 3 4 5'>file-c.orig
$ echo '2 3 4 5 6'>file-d.orig
$ < file-c.orig tr ' ' '\n' | tr -s '\n' '\n' |sort -nu > file-c.1
$ < file-d.orig tr ' ' '\n' | tr -s '\n' '\n' |sort -nu > file-d.1
$ diff file-c.1 file-d.1
1d0
< 1
5a5
> 6
Это определяет
Например: file1 = 1 3 1 4 5 и file2 = 5 1 4 3 6, ожидаемый вывод: 1 6.
$ echo '1 3 1 4 5'>file-e.orig
$ echo '5 1 4 3 6'>file-f.orig
$ < file-e.orig tr ' ' '\n' | tr -s '\n' '\n' |sort -nu > file-e.1
$ < file-f.orig tr ' ' '\n' | tr -s '\n' '\n' |sort -nu > file-f.1
$ diff file-e.1 file-f.14a5
> 6
$ comm -3 <( cat file-e.orig | tr ' \t' '\n' | sort) <(cat file-f.orig | tr ' \t' '\n' | sort) | sort -u
1
6
$ awk -v RS='[[:space:]]+' 'FNR==NR {a[$0]++; next} {a[$0]--} END {for (i in a) if (a[i] != 0) print i}' file-e.orig file-f.orig
1
6
В этом случае мой метод показывает другой результат по сравнению с методами @Lety и @muru. Давайте ожидать OP, @samhitha, давайте скажем нам, что является желаемым выводом сравнения.