Использование uniq -f 1 дает неожиданные результаты

После того, как задал вопрос об ubuntuforums.org и не получил удовлетворительного ответа, я решил снова задать вопрос здесь, на Ask Ubuntu. Мне нужно, чтобы ответ был очень подробным. В частности, мне нужно знать, какие строки сравниваются каждый раз, когда строка печатается с использованием uniq для следующих двух примеров:

file1.txt:

$ cat -A file1.txt aaa^Iupc$ b$ c$ aaa^Iztp$ b$ c$ C$ A$ B$ B$ b$ $ sort file1.txt | uniq -f 1 A aaa upc aaa ztp b

и file2.txt:

$ cat -A file2.txt aaa^Iupc$ b$ c$ aaa^Iztp$ b$ c$ C$ A$ B$ B$ bbb^Ixpz$ $ sort file2.txt | uniq -f 1 A aaa upc aaa ztp b bbb xpz c

Я запутался во втором примере. Я не понимаю, как в верхнем регистре B не заканчивается окончательный вывод. Должна ли печататься строка с верхним регистром В, если строки B и bbb xpz находятся рядом друг с другом? Если:

B ---> (empty)

и

bbb ---> xpz

пустое значение и xpz являются уникальными, поэтому обе строки должны быть напечатаны. Или я что-то упускаю?

1
задан 9 June 2017 в 04:10

4 ответа

Ответ заключается в порядке сортировки и в том, что uniq использует для значения поля, когда меньше, чем заданный номер поля (N) существует при использовании -f N.

Как вы видели имеют кодировки ASCII, поэтому порядок сортировки очень предсказуем:

% sort file.txt A aaa upc aaa ztp b b B B bbb xpz c c C

Теперь давайте используем uniq -f 1 для получения уникальных строк с пропуском первого поля каждой отдельной строки при проверке:

% sort file.txt | uniq -f 1 A aaa upc aaa ztp b bbb xpz c

Теперь важно отметить, что uniq использует пустую строку для строк, которая имеет меньше упомянутых полей, 1 в этом случае; поэтому все строки, которые имеют только одно поле, будут рассматриваться как имеющие нулевые строки для других полей, в то время как по сравнению с другими строками, имеющими> = 2 поля.

Итак, из выхода sort file2.txt:

b b B B

все будут рассматриваться как одни и те же, и сохранится только первая строка, содержащая b, поэтому у вас есть b на выходе.

Точно так же из:

c c C

только выход c попадет в выход uniq.

2
ответ дан 18 July 2018 в 11:56

Вот таблица, которая может помочь вам в этом:

----------------+---------------+----------+----------------+ sort | Remove | Adjacent | | (C locale) | field #1 | match? | Output | ----------------+---------------+----------+----------------+ A | | N* |A | B | | Y | | B | | Y | | C | | Y | | aaa upc | upc | N |aaa upc | aaa ztp | ztp | N |aaa ztp | b | | N |b | b | | Y | | bbb xpz | xpz | N |bbb xpz | c | | N |c | c | | Y | | ----------------+---------------+----------+----------------+ * the first line has no adjacent above, so is always output
0
ответ дан 18 July 2018 в 11:56

Ответ заключается в порядке сортировки и в том, что uniq использует для значения поля, когда меньше, чем заданный номер поля (N) существует при использовании -f N.

Как вы видели имеют кодировки ASCII, поэтому порядок сортировки очень предсказуем:

% sort file.txt A aaa upc aaa ztp b b B B bbb xpz c c C

Теперь давайте используем uniq -f 1 для получения уникальных строк с пропуском первого поля каждой отдельной строки при проверке:

% sort file.txt | uniq -f 1 A aaa upc aaa ztp b bbb xpz c

Теперь важно отметить, что uniq использует пустую строку для строк, которая имеет меньше упомянутых полей, 1 в этом случае; поэтому все строки, которые имеют только одно поле, будут рассматриваться как имеющие нулевые строки для других полей, в то время как по сравнению с другими строками, имеющими> = 2 поля.

Итак, из выхода sort file2.txt:

b b B B

все будут рассматриваться как одни и те же, и сохранится только первая строка, содержащая b, поэтому у вас есть b на выходе.

Точно так же из:

c c C

только выход c попадет в выход uniq.

2
ответ дан 24 July 2018 в 19:53
  • 1
    ОК, но как получится набрать sort file2.txt | uniq -f 1 дает верхний регистр A и нижний регистр b во втором файле? Разве оба не должны быть исключены из сравнения и не влиять на результат? – John_Patrick_Mason 9 June 2017 в 04:56
  • 2
    @John_Patrick_Mason Expanded, проверьте сейчас. – heemayl 9 June 2017 в 05:20
  • 3
    Кажется, я понял это сейчас. Я заменил каждый алфавитный символ, который имеет только одно поле с буквой z, чтобы лучше визуализировать происходящее. Если я правильно понимаю, строки, которые имеют только одно поле, испортили то, что видит uniq. Если я прав, это так, как будто я вообще не использовал команду sort и передал uniq несортированный файл. – John_Patrick_Mason 9 June 2017 в 06:19
  • 4
    @John_Patrick_Mason Нет, не совсем. Без sort вы не получили бы залоги, отсортированные в первую очередь. SO, только последовательные строки, которые имеют одно поле в исходном файле, приведут только к первой строке. – heemayl 9 June 2017 в 06:22
  • 5
    @heemaul Когда я сказал, что заменил каждый алфавитный символ, и только одно поле с буквой z, чтобы лучше визуализировать, я имел в виду, что я создал новый файл, во-первых, на основе вывода: sort file2.txt. Имеет ли это смысл? – John_Patrick_Mason 9 June 2017 в 06:46

Вот таблица, которая может помочь вам в этом:

----------------+---------------+----------+----------------+ sort | Remove | Adjacent | | (C locale) | field #1 | match? | Output | ----------------+---------------+----------+----------------+ A | | N* |A | B | | Y | | B | | Y | | C | | Y | | aaa upc | upc | N |aaa upc | aaa ztp | ztp | N |aaa ztp | b | | N |b | b | | Y | | bbb xpz | xpz | N |bbb xpz | c | | N |c | c | | Y | | ----------------+---------------+----------+----------------+ * the first line has no adjacent above, so is always output
0
ответ дан 24 July 2018 в 19:53

Другие вопросы по тегам:

Похожие вопросы: