[РЕШЕНО] Удалить повторяющиеся строки
Модераторы: /dev/random, Модераторы разделов
[РЕШЕНО] Удалить повторяющиеся строки
С помощью sed или иначе, как удалить повторяющиеся более двух раз строки из файла?
Система -- это совокупность элементов и связей, дающая новые свойства, не присущие ни одному из элементов и ни одной из связей.
- /dev/random
- Администратор
- Сообщения: 5282
- ОС: Gentoo
Re: [РЕШЕНО] Удалить повторяющиеся строки
Если эти повторяющиеся строки всегда идут подряд, используйте uniq. Если нет - sort -u. Если во втором случае нужно, чтобы порядок строк сохранялся (sort, как ясно из имени, их отсортирует), то пронумеруйте строки, отсортируйте с удалением дублей без учёта номера (см. опцию -k), отсортируйте оставшиеся по номеру и удалите номера с помощью sed или cut.
PS: Варианты, что я перечислил, вычистят все повторы, а не только те строки, что повторяются более _двух_ раз. Но что-то мне подсказывает, что вы имели в виду более _одного_ раза.
Re: [РЕШЕНО] Удалить повторяющиеся строки
Нет, именно повторы более двух раз, т.е. если строка встречается дважды, то её не удалять.
Нашёл вот такую дикую строку:
Но она оставляет один экземпляр строки. И она выше моего понимания.
Нашёл вот такую дикую строку:
Код: Выделить всё
sed -n 'G; s/\n/&&/; /^\([ -~]*\n\).*\n\1/d; s/\n//; h; P'
Но она оставляет один экземпляр строки. И она выше моего понимания.
Система -- это совокупность элементов и связей, дающая новые свойства, не присущие ни одному из элементов и ни одной из связей.
- /dev/random
- Администратор
- Сообщения: 5282
- ОС: Gentoo
Re: [РЕШЕНО] Удалить повторяющиеся строки
newsrc писал(а): ↑08.06.2014 13:15Нет, именно повторы более двух раз, т.е. если строка встречается дважды, то её не удалять.
Нашёл вот такую дикую строку:
Код: Выделить всё
sed -n 'G; s/\n/&&/; /^\([ -~]*\n\).*\n\1/d; s/\n//; h; P'
Но она оставляет один экземпляр строки. И она выше моего понимания.
А вам не надо оставлять этот экземпляр? Всё страннее и страннее. Ну ладно.
Предполагаю, что все дубли идут подряд. Если нет, приведите текст к такому виду с помощью sort.
* с помощью uniq -c замените каждую серию дублей на длину серии и строку
* затем sed'ом замените: s/^ *2 \(.*\)/\1\n\1/ (т.е. раскройте "2 строка" в "строка \n строка")
* им же удалите из строк s/^ *1 //
* им же (или grep'ом) удалите все остальные строки
Можно в другом порядке, если удобно.
Re: [РЕШЕНО] Удалить повторяющиеся строки
/dev/random
У uniq есть опция -u, которая просто выведет все уникальные строки. Не нужно плясок с sed'ами/grep'ами.
У uniq есть опция -u, которая просто выведет все уникальные строки. Не нужно плясок с sed'ами/grep'ами.
UNIX is basically a simple operating system, but you have to be a genius to understand the simplicity. © Dennis Ritchie
The more you believe you don't do mistakes, the more bugs are in your code.
The more you believe you don't do mistakes, the more bugs are in your code.
- /dev/random
- Администратор
- Сообщения: 5282
- ОС: Gentoo
Re: [РЕШЕНО] Удалить повторяющиеся строки
SLEDopit писал(а): ↑08.06.2014 14:10/dev/random
У uniq есть опция -u, которая просто выведет все уникальные строки. Не нужно плясок с sed'ами/grep'ами.
Я знаю, но в том-то и дело, что ТС это не подходит. Строки, встречающиеся 2 раза, ему удалять не нужно.
Re: [РЕШЕНО] Удалить повторяющиеся строки
Ой, да, что-то я невнимательно прочитал, виноват.
Ну тогда, могу предложить решения для случая, если важно не нарушать порядок и размер файла относительно небольшой:
суть работы примерно такая:
создаётся массив, куда вносится весь файл (aprint), второй массив, куда вносятся строки, которые встречались хоть раз ( seen ) и третий массив, где строки, которые встречались дважды ( twice ). Если строка встречается 3 и более раз, она удаляется из seen. В конце печатаются все пересечения из seen и aprint, которые и будут искомыми строками.
Ну тогда, могу предложить решения для случая, если важно не нарушать порядок и размер файла относительно небольшой:
Код: Выделить всё
awk '{aprint[NR]=$0;if(!seen[$0]&&!twice[$0]){++seen[$0];}else{if(!twice[$0]){++twice[$0];}else{delete seen[$0]}}};END{for(i in aprint)if(seen[aprint[i]])print aprint[i];}'
суть работы примерно такая:
создаётся массив, куда вносится весь файл (aprint), второй массив, куда вносятся строки, которые встречались хоть раз ( seen ) и третий массив, где строки, которые встречались дважды ( twice ). Если строка встречается 3 и более раз, она удаляется из seen. В конце печатаются все пересечения из seen и aprint, которые и будут искомыми строками.
UNIX is basically a simple operating system, but you have to be a genius to understand the simplicity. © Dennis Ritchie
The more you believe you don't do mistakes, the more bugs are in your code.
The more you believe you don't do mistakes, the more bugs are in your code.
Re: [РЕШЕНО] Удалить повторяющиеся строки
Спасибо всем.
В процессе чтения ваших постов придумал такой вариант:
Да, постоянно делает cat файла, но размер в несколько строк позволяет так сделать.
Скрипту в качестве параметра передаётся имя файла.
В процессе чтения ваших постов придумал такой вариант:
Код: Выделить всё
#/bin/sh
foo() {
while read line; do
MATCH=`cat "${1}" | grep "${line}" | wc -l`
if [[ ${MATCH} -le 2 ]]; then
echo "${line}"
fi
done < "${1}"
}
TMP=`foo "${1}"`
echo "${TMP}" > ${1}
Да, постоянно делает cat файла, но размер в несколько строк позволяет так сделать.
Скрипту в качестве параметра передаётся имя файла.
Система -- это совокупность элементов и связей, дающая новые свойства, не присущие ни одному из элементов и ни одной из связей.
Re: [РЕШЕНО] Удалить повторяющиеся строки
можно заменить на grep -c "$line" "$1". а ещё лучше на grep -c "^$line$" "$1", иначе могут быть лишние совпадения.
ну и да, построчная обработка файла на чистом bash'e всегда существенно дольше всяких sed'ов/awk'ов.
у вас, правда, файл, судя по всему маленький. но если размер вырастет, будет тяжело.
UNIX is basically a simple operating system, but you have to be a genius to understand the simplicity. © Dennis Ritchie
The more you believe you don't do mistakes, the more bugs are in your code.
The more you believe you don't do mistakes, the more bugs are in your code.
Re: [РЕШЕНО] Удалить повторяющиеся строки
Я бы написал вот так: perl -pe '$_="" unless $x{$_}++ < 2'
Re: [РЕШЕНО] Удалить повторяющиеся строки
У вас оно выводит все повторяющиеся строки не более 2х раз (даже если оно повторяется 3 или 4 раза, 2 раза оно всё равно выведется). А ТС не нужно выводить строки, которые встречаются более 2х раз, вообще.
UNIX is basically a simple operating system, but you have to be a genius to understand the simplicity. © Dennis Ritchie
The more you believe you don't do mistakes, the more bugs are in your code.
The more you believe you don't do mistakes, the more bugs are in your code.
Re: [РЕШЕНО] Удалить повторяющиеся строки
Да, вот это ещё лучше, спасибо. И за опцию -c спасибо.
Система -- это совокупность элементов и связей, дающая новые свойства, не присущие ни одному из элементов и ни одной из связей.
- /dev/random
- Администратор
- Сообщения: 5282
- ОС: Gentoo
Re: [РЕШЕНО] Удалить повторяющиеся строки
Тогда уж лучше grep -cFx "$line", поскольку в $line может содержаться что-то, что grep примет за регулярку.
Спасибо сказали:
Re: [РЕШЕНО] Удалить повторяющиеся строки
Да, значит, не понял задания. Можно так, конечно:
perl -e 'for(@a=<>){$x{$_}++} for (@a){if($x{$_}<=2){print $_}}'
или
perl -e 'for(@a=<>){$x{$_}++} print grep {$x{$_}<=2} @a'
Но уже более громоздко.