Awk linux удалить дубликаты

Awk linux удалить дубликаты

Подскажите алгоритм!
Необходимо при помощи команд bash или awk удалить повторяющиеся сочетания в файле след. вида:
39111 39112
39111 39114
39111 39123
39112 39111 *
39112 39113
39113 39112 *
.
39123 39111 *

файл может быть до 100 строк. *-ой пометил те комбинации которые необходимо удалить!

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

Оглавление

  • Удаление повторяющихся строк (Bash или awk), madskull, 13:55 , 15-Ноя-06, (1)
    • Удаление повторяющихся строк (Bash или awk), SerVnk, 14:36 , 15-Ноя-06, (2)
      • Удаление повторяющихся строк (Bash или awk), perece, 15:36 , 15-Ноя-06, (3)
        • Удаление повторяющихся строк (Bash или awk), SerVnk, 20:31 , 15-Ноя-06, (4)

Сообщения по теме [Сортировка по времени, UBB]

>Подскажите алгоритм!
>Необходимо при помощи команд bash или awk удалить повторяющиеся сочетания в файле
>след. вида:
>39111 39112
>39111 39114
>39111 39123
>39112 39111 *
>39112 39113
>39113 39112 *
>.
>39123 39111 *
>
>файл может быть до 100 строк. *-ой пометил те комбинации которые необходимо
>удалить!

sort -u
или
sort | uniq

1. «Удаление повторяющихся строк (Bash или awk)»
Сообщение от madskull (ok) on 15-Ноя-06, 13:55
Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

2. «Удаление повторяющихся строк (Bash или awk)»
Сообщение от SerVnk (ok) on 15-Ноя-06, 14:36

>>Подскажите алгоритм!
>>Необходимо при помощи команд bash или awk удалить повторяющиеся сочетания в файле
>>след. вида:
>>39111 39112
>>39111 39114
>>39111 39123
>>39112 39111 *
>>39112 39113
>>39113 39112 *
>>.
>>39123 39111 *
>>
>>файл может быть до 100 строк. *-ой пометил те комбинации которые необходимо
>>удалить!
>
>sort -u
>или
>sort | uniq

sort -u удалит мне повторяющиеся строчки, а мне необходимо избавиться от повторных сочетаний. Например:
39111 39112
39112 39111
нужно удалить вторую строчку т.к. такое сочетание цифр уже есть в первой строке

Источник

Удалите дубликаты записей $ PATH с помощью команды awk

Я пытаюсь написать функцию оболочки bash, которая позволит мне удалять дубликаты копий каталогов из моей переменной среды PATH.

Мне сказали, что это можно сделать с помощью одной строки, используя awk команду, но я не могу понять, как это сделать. Кто-нибудь знает как?

Если у вас еще нет дубликатов в PATH и вы хотите добавлять каталоги только в том случае, если их еще нет, вы можете легко сделать это с помощью одной оболочки.

А вот фрагмент оболочки, из которого удаляются дубликаты $PATH . Он просматривает записи одну за другой и копирует те, которые еще не видели.

Вот понятное однострочное решение, которое делает все правильно: удаляет дубликаты, сохраняет порядок путей и не добавляет двоеточие в конце. Поэтому он должен дать вам дедуплицированную переменную PATH, которая будет вести себя точно так же, как и оригинал:

Он просто разделяется на двоеточие ( split(/:/, $ENV) ), использует использование grep < not $seen<$_>++ > для фильтрации любых повторяющихся экземпляров путей, за исключением первого вхождения, а затем объединяет оставшиеся вместе, разделенные двоеточиями, и печатает результат ( print join(«:», . ) ).

Если вам нужна дополнительная структура, а также возможность дедупликации других переменных, попробуйте этот фрагмент, который я сейчас использую в своей конфигурации:

Этот код дедуплицирует как PATH, так и MANPATH, и вы можете легко вызывать dedup_pathvar другие переменные, которые содержат разделенные двоеточиями списки путей (например, PYTHONPATH).

Дольше (чтобы увидеть, как это работает):

Хорошо, так как вы новичок в Linux, вот как на самом деле установить PATH без завершающего «:»

Кстати, убедитесь, что в вашей переменной PATH нет каталогов, содержащих «:», иначе это может привести к путанице.

Вот один лайнер AWK.

  • printf %s «$PATH» печатает содержимое $PATH без завершающей строки
  • RS=: изменяет символ разделителя входной записи (по умолчанию — новая строка)
  • ORS= изменяет разделитель выходной записи на пустую строку
  • a имя неявно созданного массива
  • $0 ссылается на текущую запись
  • a[$0] является ассоциативным массивом разыменования
  • ++ это оператор постинкрементного
  • !a[$0]++ защищает правую сторону, то есть он гарантирует, что текущая запись будет напечатана, только если она не была напечатана ранее
  • NR номер текущей записи, начиная с 1

Это означает, что AWK используется для разделения PATH содержимого по : символам разделителя и для фильтрации повторяющихся записей без изменения порядка.

Поскольку ассоциативные массивы AWK реализованы в виде хеш-таблиц, время выполнения является линейным (т. Е. В O (n)).

Обратите внимание, что нам не нужно искать : символы в кавычках, потому что оболочки не предоставляют кавычки для поддержки каталогов с : именем в PATH переменной.

Awk + паста

Вышесказанное можно упростить с помощью пасты:

Команда paste используется для разбивки выходных данных awk двоеточиями. Это упрощает действие awk для печати (действие по умолчанию).

Источник

Как удалить дубликаты строк внутри текстового файла?

Огромный (до 2 ГиБ) мой текстовый файл содержит около 100 точных дубликатов каждой строки в нем (в моем случае это бесполезно, поскольку файл представляет собой таблицу данных, похожую на CSV).

Что мне нужно, так это удалить все повторения, при этом (желательно, но этим можно пожертвовать ради значительного повышения производительности), сохраняя первоначальный порядок последовательности. В результате каждая строка должна быть уникальной. Если было 100 одинаковых строк (обычно дубликаты распределяются по файлу и не будут соседями), остается только один из них.

Я написал программу на Scala (рассмотрим Java, если вы не знаете о Scala), чтобы реализовать это. Но, может быть, есть более быстрые собственные инструменты, написанные на C, способные сделать это быстрее?

ОБНОВЛЕНИЕ: awk ‘!seen[$0]++’ filename решение, казалось, работало очень хорошо для меня, пока файлы были около 2 ГБ или меньше, но теперь, когда я собираюсь очистить файл 8 ГБ, оно больше не работает. Кажется, что бесконечность на Mac с 4 ГБ ОЗУ и 64-битном ПК с Windows 7 с 4 ГБ ОЗУ и подкачкой 6 ГБ просто не хватает памяти. И я не испытываю энтузиазма по поводу того, чтобы попробовать это на Linux с 4 ГБ RAM, учитывая этот опыт.

awk Решение видно на #bash (Freenode):

Существует простой (не сказать очевидный) метод, использующий стандартные утилиты, который не требует большого объема памяти, кроме как для запуска sort , который в большинстве реализаций имеет специфические оптимизации для больших файлов (хороший алгоритм внешней сортировки). Преимущество этого метода в том, что он зацикливается только на всех строках внутри специальных утилит, а не внутри интерпретируемых языков.

Если все строки начинаются с непробельного символа, вы можете обойтись без некоторых параметров:

Для большого количества дублирования метод, который требует только сохранения одной копии каждой строки в памяти, будет работать лучше. С некоторыми дополнительными интерпретациями для этого есть очень лаконичный сценарий awk (уже опубликованный enzotib ):

Менее сжато: !seen[$0] то есть вывести текущую строку, если она еще не видна, затем увеличить seen счетчик для этой строки (неинициализированные переменные или элементы массива имеют числовое значение 0).

Для длинных строк вы можете сэкономить память, сохраняя только несанкционированную контрольную сумму (например, криптографический дайджест) каждой строки. Например, используя SHA-1, вам нужно всего 20 байтов плюс постоянные издержки на строку. Но вычисление дайджестов происходит довольно медленно; Этот метод выиграет, только если у вас быстрый ЦП (особенно с аппаратным ускорителем для вычисления дайджестов) и не достаточно памяти относительно размера файла и достаточно длинных строк. Никакая базовая утилита не позволяет вычислить контрольную сумму для каждой строки; вам придется нести ответственность за интерпретацию Perl / Python / Ruby /… или написать специальную скомпилированную программу.

Источник

Как удалить повторяющиеся строки в файле без сортировки в Unix?

Есть ли способ удалить повторяющиеся строки в файле в Unix?

Я могу сделать это с sort -u и uniq команд, но я хочу использовать sed или awk . Это возможно?

seen — это ассоциативный массив, в который Awk будет передавать каждую строку файла. Если строки нет в массиве, seen[$0] будет присвоено значение false. Это ! логический оператор НЕ, который преобразует ложное в истинное. Awk напечатает строки, в которых выражение оценивается как истинное. В ++ приросты seen так , что seen[$0] == 1 после того, как в первый раз строка найдена , а затем seen[$0] == 2 , и так далее.
Awk оценивает все, кроме 0 и «» (пустая строка), как истина. Если в него помещена повторяющаяся строка, seen тогда !seen[$0] будет вычислено значение false, и строка не будет записана на вывод.

Из http://sed.sourceforge.net/sed1line.txt : (Пожалуйста, не спрашивайте меня, как это работает ;-))

] * \ n). * \ n \ 1 / d; s / \ п //; час; P ‘означает, грубо говоря, «Добавить все пространство удержания к этой строке, затем, если вы видите дублированную строку, выбросите все это, в противном случае скопируйте весь беспорядок обратно в пространство удержания и распечатайте первую часть (это строка, которую вы просто читать »

] представляет собой диапазон символов ASCII от 0x20 (пробел) до 0x7E (тильда). Они рассматриваются в печатаемые символы ASCII (связанная страница также 0x7F / удаления , но это не кажется правильным). Это делает решение неработоспособным для тех, кто не использует ASCII, или для тех, кто использует, скажем, символы табуляции. Более переносимый [^\n] включает в себя намного больше символов . фактически все, кроме одного.

Однострочник Perl, аналогичный awk-решению @jonas:

Этот вариант удаляет завершающие пробелы перед сравнением:

Этот вариант редактирует файл на месте:

Этот вариант редактирует файл на месте и делает резервную копию file.bak

Однострочник, опубликованный Андре Миллером выше, работает, за исключением последних версий sed, когда входной файл заканчивается пустой строкой и без символов. На моем Mac мой процессор просто крутится.

Бесконечный цикл, если последняя строка пуста и не содержит символов :

Не зависает, но вы теряете последнюю строчку

Объяснение находится в самом конце FAQ по sed :

Сопровождающий GNU sed чувствовал, что, несмотря на проблемы с переносимостью, которые
это может вызвать, изменение команды N на печать (а не
удаление) пространства шаблонов больше соответствовало интуитивным представлениям
о том, как должна себя вести команда для «добавления следующей строки» .
Другой факт, благоприятствующий изменению, заключался в том, что «»
удалит последнюю строку, если в файле нечетное количество строк, но
напечатает последнюю строку, если в файле четное количество строк.

Чтобы преобразовать сценарии, в которых использовалось прежнее поведение N (удаление
пространства шаблонов при достижении EOF), в сценарии, совместимые со
всеми версиями sed, измените одиночный «N;» в «$ d; N;» ,

Альтернативный способ использования Vim (совместимый с Vi) :

Удалите повторяющиеся последовательные строки из файла:

vim -esu NONE +’g/\v^(.*)\n\1$/d’ +wq

Удалите повторяющиеся, непоследовательные и непустые строки из файла:

Первое решение также из http://sed.sourceforge.net/sed1line.txt

  1. $!N; : если текущая строка НЕ ​​является последней строкой, используйте N команду для чтения следующей строки pattern space .
  2. /^(.*)\n\1$/!P : если содержимое текущей строки разделено pattern space двумя duplicate string символами \n , что означает, что следующая строка является строкой same с текущей строкой, мы НЕ можем распечатать ее в соответствии с нашей основной идеей; в противном случае, что означает, что текущая строка является ПОСЛЕДНИМ появлением всех повторяющихся последовательных строк, теперь мы можем использовать P команду для печати символов в текущей pattern space утилите \n ( \n также напечатанной).
  3. D : мы используем D команду для удаления символов в текущей pattern space утилите \n ( \n также удаленной), тогда содержимое pattern space следующей строки.
  4. и D команда заставит sed перейти к своей FIRST команде $!N , но НЕ будет читать следующую строку из файла или стандартного входного потока.

Второе решение легко понять (от себя):

  1. прочтите новую строку из входного потока или файла и распечатайте ее один раз.
  2. используйте :loop команду set a label named loop .
  3. используйте N для чтения следующей строки в pattern space .
  4. используйте s/^(.*)\n\1$/\1/ для удаления текущей строки, если следующая строка совпадает с текущей строкой, мы используем s команду для выполнения delete действия.
  5. если s команда выполнена успешно, то используйте tloop команду force, sed чтобы перейти к label названному loop , что сделает тот же цикл для следующих строк, при этом не будет повторяющихся последовательных строк строки, которая есть latest printed ; в противном случае используйте D команду для delete строки, которая совпадает с latest-printed line , и принудительный sed переход к первой команде, которая является p командой, содержимое текущей pattern space является следующей новой строкой.

Источник

Читайте также:  Asus s46c windows 10
Оцените статью