Форум программистов, компьютерный форум, киберфорум
Shell, Bash
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.79/34: Рейтинг темы: голосов - 34, средняя оценка - 4.79
50 / 16 / 11
Регистрация: 27.03.2013
Сообщений: 789
1

Удаление полностью идентичных (дублирующихся строк) при использовании sed

06.07.2017, 16:49. Показов 6957. Ответов 10
Метки нет (Все метки)

Вот исходный текст, перед некоторыми строками используется знак табуляции, а некоторые используют символы пробела.
Обозначу для примера строки со знаком табуляции

Кликните здесь для просмотра всего текста
\tworkgroup = WORKGROUP
\tworkgroup = WORKGROUP
\tworkgroup = WORKGROUP

workgroup = WORKGROUP
workgroup = WORKGROUP33
workgroup = WORKGROUP22
workgroup= WORKGROUP
workgroup=WORKGROUP22

Интересное предположение

\tsamba = SAMBA
\tsamba = SAMBA
work = ws-1



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

Кликните здесь для просмотра всего текста
Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#!/usr/bin/env bash
 
# удаление повторяющихся строк
 
file=./smb2.conf
 
function delete_duplicate_str(){
dub=$(sort $file | uniq -d)
 
 if  [[ -n "${dub}"  ]] 
 then
 echo
 echo -e  "Найдены идентичные строки :\n ${dub}"
 echo
local et=$1
local et2=$2
#reg=$(grep -Px "\t${et} = .*" $file)
duplicate_1=$(grep -Px "^\t${et}\s=\s${et2}$" $file)
duplicate_2=$(grep -Px "^\t${et}\s=.*$" $file)
 
      if [[ -n "${duplicate_1}" ]]
    then
        echo
        echo  -e "Найдено полностью идентичных совпадений опций по умолчанию:\n ${duplicate_1} "
        echo
        echo -e "Удалим только похожие совпадения "
       sed -i -r "/${et}\s*=/{/^\t${et}\s= \b${et2}\b/! d}" $file
   else
       echo "совпадений не найдено"
      #sed -i -r "/${et}\s*=/{/^\tw.* = \b${et2}\b/! d}" $file
      fi
 else
     echo "совпадений нет"
 fi 
 
# -n -проверяет, что строка не пустая
}
 
 
 delete_duplicate_str "workgroup" "WORKGROUP" 
 
 # delete_duplicate_str "samba" "SAMBA"
 
 
 # local et=$1 
 # $1 - 1-й аргумент - это эталонное слово для поиска нужной опции
 # local et=$2 
 # $2 - 2-й аргумент - это эталонное слово для поиска значения
 # по умолчанию соответствующей опции
 # duplicate_1 - данная переменная содержит вычисляемое выражение - $(выражение)
 #  это выражение позволяет определить есть ли в данном файле опций со значениями по умолчанию
 # 
  # grep -Px - поиск слов с применением регулярных выражений
  # -P или --perl-regexp  - этот ключ, означает использование  ШАБЛОНа - регулярного выражения языка Perl
  # -x  -  поиск точного вхождения слова
  # ^ - якорь в регулярных выражениях, означает "начало строки"
  # \s - один пробельный символ
  # $  - якорь в регулярных выражениях, означает "конец строки"



Пробовал так

Bash
1
 delete_duplicate_str "workgroup" "WORKGROUP" < sed  "2,$d
или так

Bash
1
 delete_duplicate_str "workgroup" "WORKGROUP" | sed  "2,$d
Не работает.
Может ли утилита sed справиться с этой задачей ?
0

Помощь в написании контрольных, курсовых и дипломных работ здесь.

Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
06.07.2017, 16:49
Ответы с готовыми решениями:

Удаление дублирующихся строк dataGridView
Я хочу или удалить, или скрыть повторяющиеся строки в dataGridView. Делаю это в цикле, но удаляет...

Удаление дублирующихся строк в dataset
Приветствую. Нужно удалить дубликаты строк в DS, но .net 2.0 и сравнивание идет не по одному или...

Сложный запрос на удаление дублирующихся строк
Имеется такой запрос (где id - уникальный ключ и автоинкремент) : DELETE FROM `myTable` WHERE `id`...

Удаление дублирующихся данных при переносе
Добрый день! Нужна помощь в следующем вопросе. Есть таблица с определенным набором столбцов...

10
Нарушитель
3196 / 1074 / 293
Регистрация: 07.05.2015
Сообщений: 2,182
06.07.2017, 18:58 2
Может, только непонятно чем uniq не угодил?
Bash
1
sed -E '$!N; /^(.*)\n\1$/!P; D' file
1
Модератор
Эксперт NIX
2784 / 2032 / 680
Регистрация: 02.03.2015
Сообщений: 6,514
07.07.2017, 10:07 3
Цитата Сообщение от masli Посмотреть сообщение
функцию по удалению похожих строк в конфигурационном файле, но полностью идентичные строки не получается удалить
Вы ставите странные задачи и скорее всего сами не понимаете что должно в итоге получится. Что в Вашем понимании «полностью идентичные» и почему надо удалять только их?
0
50 / 16 / 11
Регистрация: 27.03.2013
Сообщений: 789
07.07.2017, 10:46  [ТС] 4
Цитата Сообщение от greg zakharov Посмотреть сообщение
Может, только непонятно чем uniq не угодил?
Если uniq может удалить подряд идущие индентичные строки , а также расположенные не подряд в файле , а через какие-либо другие строки, как в примере выше) и
может ли uniq удалить дубликаты строк непосредственно в проверяемом файле, не меняя структуру файла (не удаляя например пустых строк ), оставляя оригиналы строк на тех местах, где они находятся в файле , тогда покажите пример кода.
Я например, нашел только вот такую конструкцию работы uniq

uniq имя_файла_входящего имя_файла_выходящего

что неподходит.

Цитата Сообщение от Marinero Посмотреть сообщение
«полностью идентичные» и почему надо удалять только их?
я уже писал выше, «полностью идентичные» - это строка , которая повторяют собой копию предыдущей (символы \s и \t визуально ничем не отличишь, но команды grep -x или uniq -D - это отличие видят)

При этом эти строки не всегда идут подряд и могут находится в разных местах документа, большие документы просматривать на наличие дублирующихся строк просматривать неудобно, решил это автоматизировать.
использую sed, так как об этой команде немного больше знаю, с ней привычней работать
0
Модератор
Эксперт NIX
2784 / 2032 / 680
Регистрация: 02.03.2015
Сообщений: 6,514
07.07.2017, 12:20 5
Bash
1
sed -z ':1;s/\(\(\s*\S\+\s\?=\s\?\S\+\n\).*\)\2/\1/;t1'
Преобразует Ваш пример в
Код
	workgroup = WORKGROUP

workgroup = WORKGROUP33
workgroup = WORKGROUP22 
workgroup= WORKGROUP
workgroup=WORKGROUP22

Интересное предположение

	samba = SAMBA
work = ws-1
Хотя, хоть убейте не могу понять необходимость в исключительной идентичности. Какой смысл в одновременном наличии в конфиге \tworkgroup = WORKGROUP vs workgroup= WORKGROUP? Да и вообще в конфиге параметр должен быть в единственном числе: один workgroup=, один samba=, один work= и т.д.
0
50 / 16 / 11
Регистрация: 27.03.2013
Сообщений: 789
07.07.2017, 14:02  [ТС] 6
Цитата Сообщение от Marinero Посмотреть сообщение
Какой смысл в одновременном наличии в конфиге \tworkgroup = WORKGROUP vs workgroup= WORKGROUP? Да и вообще в конфиге параметр должен быть в единственном числе: один workgroup=, один samba=, один work= и т.д.
так ведь это всего лишь пример и все, и ничего больше...
Ну появились там похожие строки, как уже не важно и их нужно убрать, поэтому просто запускаю проверку файла и удаляю не нужное.
Есть какой-то стиль форматирования строк в файле, пусть будет так...
Под это и пишется обработка строк и соответственно опции, которые добавит сценарий будут в том же стиле форматирования строк и будут добавлены в конфигурационный файл
Во время отработки сценария появляются дубликаты строк... (я учусь...)
Вручную удалять их или подставлять сценарию новый оригинальный файл нет желания, поэтому и хочу написать обработку, а удаление опций-дубликатов в файле...
Да мало ли применений, тем более , что не я 1-й задаю такие вопросы, по поводу дубликата строк,
Другое дело что найденные примеры не всегда работают, как например вот этот пример, найденный в сети

Bash
1
2
3
# удалить дублирующиеся непоследовательные строки файла. Острожнее с
# переполнением размера буфера, занятой памяти, лучше используйте GNU sed!
sed -n 'G; s/n/&&/; /^([ -~]*n).*n1/d; s/n//; h; P'
Появилась вот такая проблема при написании сценария, так почему бы ее не автоматизировать, а не вручную сидеть и чистить конфигурационный файл ?

Добавлено через 41 минуту
Цитата Сообщение от Marinero Посмотреть сообщение
sed -z ':1;s/\(\(\s*\S\+\s\?=\s\?\S\+\n\).*\)\2/\1/;t1'
Вот я написал небольшой сценарий, с тем примером текстового файла, который предоставил

Кликните здесь для просмотра всего текста
Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#!/usr/bin/env bash
 
echo -e  "\tworkgroup = WORKGROUP
\tworkgroup = WORKGROUP
\tworkgroup = WORKGROUP
 
workgroup = WORKGROUP
workgroup = WORKGROUP33
workgroup = WORKGROUP22
workgroup= WORKGROUP
workgroup=WORKGROUP22
 
Интересное предположение
 
\tsamba = SAMBA
\tsamba = SAMBA
work = ws-1" >  ./smb5.conf
echo
cat ./smb5.conf
echo
 
file=./smb5.conf
 
 sed -iz ":1;s/\(\(\s*\S\+\s\?=\s\?\S\+\n\).*\)\2/\1/;t1" $file
 
# z - В новейших версиях GNU sed появилась новая команда z, она очищает буфер. 
# Однако, пока ещё в большинстве систем эта версия не установлена, и очищать приходится 
# командой s/.*//, что во первых не работает если в буфере есть НЕСИМВОЛЫ, 
# и во вторых теряется флаг для команд перехода
# (начиная с версии GNU sed 4.2)


Он ничего не изменил.

Добавлено через 39 минут
greg zakharov - предложил такой вариант

Bash
1
sed -E '$!N; /^(.*)\n\1$/!P; D' file
Он действительно чистит, но не может
- удалить слова, которые сразу от начала строки пишутся
- не воспринимает кириллицу
- а так же не может найти дубликаты идущие не один за другим (хотя в большей части он нашел)



Кликните здесь для просмотра всего текста
Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#!/usr/bin/env bash
 
file=./smb6.conf
 
echo -e  "\tworkgroup = WORKGROUP
\tworkgroup = WORKGROUP
\tworkgroup = WORKGROUP
 
workgroup = WORKGROUP
workgroup = WORKGROUP33
workgroup = WORKGROUP22
workgroup= WORKGROUP
workgroup=WORKGROUP22
 
Интересное предположение
 
\tsamba = SAMBA
\tsamba = SAMBA
work = ws-1
    
    workgroup = WORKGROUP
\tworkgroup = WORKGROUP
 
Интересное предположение
Интересное предположение
 
\tworkgroup = WORKGROUP 
 
Pattern = 1235
Pattern = 1235
        Интересное предположение
Интересное предположение
 
Intresting words
Intresting words
 
 Intresting words
 Intresting words
 
Шаблон = 123456
Шаблон = 123456       
 
Intresting words
    Intresting words
\tsamba = SAMBA
 
work = ws-1
Шаблон = 123456  " >  $file
 
echo
cat $file
echo
  sed -Ei '$!N; /^(.*)\n\1$/!P; D'  $file



Вопрос?

/^(.*)\n\1$/ - это, как я понимаю шаблон, по которому ищется вхождение
- от начала и до конца строки искать любое количество символов, исключая символ перевода новой строки
\1 - 1-я найденная строка , согласно данному шаблону
/... \1 / ! ; D - удалить все найденные строки, соответствующие шаблону, кроме 1-й найденной
P - Записывает шаблон до первого символа новой строки,
на стандартный вывод.
N – заглавная N, позволяет вывести номера строк, и символ перевода новой строки \n

Но вот такая связка, что означает и для чего
$!N - ?
!P - ?
0
Модератор
Эксперт NIX
2784 / 2032 / 680
Регистрация: 02.03.2015
Сообщений: 6,514
07.07.2017, 18:52 7
Цитата Сообщение от masli Посмотреть сообщение
Он ничего не изменил.
Что Вы делаете, как Вы делаете?
Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
> echo -e  "\tworkgroup = WORKGROUP
> \tworkgroup = WORKGROUP
> \tworkgroup = WORKGROUP
>  
> workgroup = WORKGROUP
> workgroup = WORKGROUP33
> workgroup = WORKGROUP22
> workgroup= WORKGROUP
> workgroup=WORKGROUP22
>  
> Интересное предположение
>  
> \tsamba = SAMBA
> \tsamba = SAMBA
> work = ws-1" | sed -z ":1;s/\(\(\s*\S\+\s\?=\s\?\S\+\n\).*\)\2/\1/;t1"
    workgroup = WORKGROUP
 
workgroup = WORKGROUP33
workgroup = WORKGROUP22
workgroup= WORKGROUP
workgroup=WORKGROUP22
 
Интересное предположение
 
    samba = SAMBA
work = ws-1
Добавлено через 3 часа 42 минуты
Для не очень больших файлов можно
Bash
1
sed -r ':a; $ ! N ; $ ! ba ; /^(.*\n).*\1/! P ; /^\s*\n/P ; D'
Ну или классика
Bash
1
awk '! NF || ! seen[$0]++'
0
7 / 6 / 4
Регистрация: 21.05.2017
Сообщений: 60
24.07.2017, 17:55 8
Выкладываю честно стыренный где-то ранее (где не помню) мною код для удаления одинаковых строк, идущих не подряд.
Я не говорю что он элегантен или короток. Просто он у меня был

Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#!/bin/bash
 
# определяет повторяющиеся строки в файле
# оставляет в файле только одну из повторяющихся строк
 
error()
{
    echo "error: $1" 1>&2
}
 
remdups()
{
    local fname=$1 tmpname
    
    tmpname=${fname}_
    
    if sort -u "$fname" > "$tmpname"; then
        mv -f "$tmpname" "$fname"
    else
        [ -f "$tmpname" ] && rm -f "$tmpname"
    fi
}
 
selfile()
{
    echo "Select file"
    n=0
    while true; do
        read -p "Enter: " fname
        ((n++))
        if [ -f "$fname" ]; then
            echo -n "Processing $fname... "
            remdups "$fname" && echo "ok"
            break
        elif [ $n -lt 3 ]; then
            error "no such file"
        else
            error "all names are wrong"
            break
        fi
    done
}
 
readfile()
{
    echo "Read file"
    n=0
    while true; do
        read -p "Enter: " fname
        ((n++))
        if [ -f "$fname" ]; then
            cat "$fname"
            break
        elif [ $n -lt 3 ]; then
            error "no such file"
        else
            error "all names are wrong"
            break
        fi
    done
}
 
cont=1
while [ $cont -eq 1 ]; do
    select ch in "Select" "List" "Read" "Exit"; do
        case "$ch" in
          "Select") selfile;;
          "List") ls;;
          "Read") readfile;;
          "Exit") cont=0; break;;
        esac 
    done
done
 
exit 0
0
1 / 1 / 0
Регистрация: 23.07.2013
Сообщений: 72
15.02.2019, 05:20 9
а, как удалить только те строки из файла, которые повторяются больше 4 раз например. Тут можно так?
Bash
1
sed -E '$!N; /^(.*)\n\1$/!P; D' file
Добавлено через 17 минут
даже, скорее так
Bash
1
awk 'seen[$0]++'
, только если нужно удалять только те строки, которые повторяются больше 4 раз, нужно
Bash
1
seen[$4]
записать?
0
3685 / 1492 / 255
Регистрация: 10.12.2013
Сообщений: 5,094
15.02.2019, 16:14 10
Цитата Сообщение от MaximRTS Посмотреть сообщение
Тут можно так?
Тут можно вспомнить, что текстовые строки удаляются в текстовых редакторах.
самые замысловатые сценарии реализуются совершенно житейским( присущим данному редактору) способом.
1
1 / 1 / 0
Регистрация: 23.07.2013
Сообщений: 72
15.02.2019, 17:44 11
Смогу разобраться, наверное, как в экселе или нотпаде удалить дубликаты, но как удалить удалить дубликаты повторяющиеся больше n раз?
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
15.02.2019, 17:44

Помощь в написании контрольных, курсовых и дипломных работ здесь.

Чтение из массива файлов и удаление дублирующихся строк в каждом файле массива
Добрый день, сейчас я только начал изучать powershell и программирование в целом, и сейчас у меня...

Удаление дублирующихся элементов
Не могу найти ошибку, прога задает рандомный вектор в определенном диапазоне, а потом сортирует его...

Удаление дублирующихся значений
Доброе время суток! Нужно удалить из таблицы из 2-х колонок строки с дубляжами, НО в первой колонке...

Удаление дублирующихся гласных из файла
доброго времени суток необходимо написать программу удаления дублирующихся гласных из текстого...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.