LINUX.ORG.RU

История изменений

Исправление papin-aziat, (текущая версия) :

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

$ cat test
         j

        ii
         j

       hhh
        ii
      gggg

       hhh
     fffff
      gggg

    eeeeee
     fffff
   ddddddd

    eeeeee
  cccccccc
   ddddddd

 bbbbbbbbb
  cccccccc
aaaaaaaaaa

 bbbbbbbbb
aaaaaaaaaa

Убираем пробелы, добавляем номера строк, сортируем по второму полю

$ grep -vn '^$' test | sort -t':' -k2
1:         j
4:         j
3:        ii
7:        ii
10:       hhh
6:       hhh
12:      gggg
8:      gggg
11:     fffff
15:     fffff
14:    eeeeee
18:    eeeeee
16:   ddddddd
20:   ddddddd
19:  cccccccc
23:  cccccccc
22: bbbbbbbbb
26: bbbbbbbbb
24:aaaaaaaaaa
27:aaaaaaaaaa

Неудача! Он сортирует учитывая ведущие пробелы! Добавляем ключ -b

$ grep -vn '^$' test | sort -t':' -k2b
24:aaaaaaaaaa
27:aaaaaaaaaa
22: bbbbbbbbb
26: bbbbbbbbb
19:  cccccccc
23:  cccccccc
16:   ddddddd
20:   ddddddd
14:    eeeeee
18:    eeeeee
11:     fffff
15:     fffff
12:      gggg
8:      gggg
10:       hhh
6:       hhh
3:        ii
7:        ii
1:         j
4:         j

Лучше, но есть проблема с номерами строк — ключом -u или uniq будут оставлены первые уникальные строки. Кстати, это не проблема, но надо следовать задуманному! Теперь придётся ещё отсортировать по первому полю в обратном порядке

$ grep -vn '^$' test | sort -t':' -k2b -k1,1r
27:aaaaaaaaaa
24:aaaaaaaaaa
26: bbbbbbbbb
22: bbbbbbbbb
23:  cccccccc
19:  cccccccc
20:   ddddddd
16:   ddddddd
18:    eeeeee
14:    eeeeee
15:     fffff
11:     fffff
8:      gggg
12:      gggg
6:       hhh
10:       hhh
7:        ii
3:        ii
4:         j
1:         j

Да блин, лексикографический порядок! Добавляем ключ -n

$ grep -vn '^$' test | sort -t':' -k2b -k1,1rn
27:aaaaaaaaaa
24:aaaaaaaaaa
26: bbbbbbbbb
22: bbbbbbbbb
23:  cccccccc
19:  cccccccc
20:   ddddddd
16:   ddddddd
18:    eeeeee
14:    eeeeee
15:     fffff
11:     fffff
12:      gggg
8:      gggg
10:       hhh
6:       hhh
7:        ii
3:        ii
4:         j
1:         j

Есть же! Вот теперь можно удалять дубликаты, но нужен ещё конвеер, увы

$ grep -vn '^$' test | sort -t':' -k2b -k1,1rn | sort -t':' -k2b -u
27:aaaaaaaaaa
26: bbbbbbbbb
23:  cccccccc
20:   ddddddd
18:    eeeeee
15:     fffff
12:      gggg
10:       hhh
7:        ii
4:         j

Переворачиваем поле с номерами строк (ещё конвеер, мда…)

$ grep -vn '^$' test | sort -t':' -k2b -k1,1rn | sort -t':' -k2b -u | sort -t':' -k1,1
10:       hhh
12:      gggg
15:     fffff
18:    eeeeee
20:   ddddddd
23:  cccccccc
26: bbbbbbbbb
27:aaaaaaaaaa
4:         j
7:        ii

Да блииин! Лексикографический, сцуко! Не забывай ключ -n!

$ grep -vn '^$' test | sort -t':' -k2b -k1,1rn | sort -t':' -k2b -u | sort -k1,1n
4:         j
7:        ii
10:       hhh
12:      gggg
15:     fffff
18:    eeeeee
20:   ddddddd
23:  cccccccc
26: bbbbbbbbb
27:aaaaaaaaaa

Фух, теперь можно убрать номера строк

$ grep -vn '^$' test | sort -t':' -k2b -k1,1rn | sort -t':' -k2b -u | sort -t':' -k1,1n | sed -E 's/^[0-9]+://'
         j
        ii
       hhh
      gggg
     fffff
    eeeeee
   ddddddd
  cccccccc
 bbbbbbbbb
aaaaaaaaaa

Ну, вот так вроде должно работать нормально.

Вот он, кровавый Unix Way!

file=$1
list=$(grep -vn '^$' $file |
       sort -t':' -k2b -k1,1rn |
       sort -t':' -k2b -u |
       sort -t':' -k1,1n |
       sed -E 's/^[0-9]+://')
echo "$list" > $file

С виду работает как надо, как ещё точнее проверить уже не знаю 😀

UPD А нет, чё-то поломалось

[me bash_playground]$ cp history_full history
[me bash_playground]$ bash foobar history
[me bash_playground]$ diff <(sort -u history_full) <(sort history)
1d0
< 
5,6d3
<           some
<          some
9,10d5
<      text
<    text
4042d4036
< text

Исходная версия papin-aziat, :

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

$ cat test
         j

        ii
         j

       hhh
        ii
      gggg

       hhh
     fffff
      gggg

    eeeeee
     fffff
   ddddddd

    eeeeee
  cccccccc
   ddddddd

 bbbbbbbbb
  cccccccc
aaaaaaaaaa

 bbbbbbbbb
aaaaaaaaaa

Убираем пробелы, добавляем номера строк, сортируем по второму полю

$ grep -vn '^$' test | sort -t':' -k2
1:         j
4:         j
3:        ii
7:        ii
10:       hhh
6:       hhh
12:      gggg
8:      gggg
11:     fffff
15:     fffff
14:    eeeeee
18:    eeeeee
16:   ddddddd
20:   ddddddd
19:  cccccccc
23:  cccccccc
22: bbbbbbbbb
26: bbbbbbbbb
24:aaaaaaaaaa
27:aaaaaaaaaa

Неудача! Он сортирует учитывая ведущие пробелы! Добавляем ключ -b

$ grep -vn '^$' test | sort -t':' -k2b
24:aaaaaaaaaa
27:aaaaaaaaaa
22: bbbbbbbbb
26: bbbbbbbbb
19:  cccccccc
23:  cccccccc
16:   ddddddd
20:   ddddddd
14:    eeeeee
18:    eeeeee
11:     fffff
15:     fffff
12:      gggg
8:      gggg
10:       hhh
6:       hhh
3:        ii
7:        ii
1:         j
4:         j

Лучше, но есть проблема с номерами строк — ключом -u или uniq будут оставлены первые уникальные строки. Кстати, это не проблема, но надо следовать задуманному! Теперь придётся ещё отсортировать по первому полю в обратном порядке

$ grep -vn '^$' test | sort -t':' -k2b -k1,1r
27:aaaaaaaaaa
24:aaaaaaaaaa
26: bbbbbbbbb
22: bbbbbbbbb
23:  cccccccc
19:  cccccccc
20:   ddddddd
16:   ddddddd
18:    eeeeee
14:    eeeeee
15:     fffff
11:     fffff
8:      gggg
12:      gggg
6:       hhh
10:       hhh
7:        ii
3:        ii
4:         j
1:         j

Да блин, лексикографический порядок! Добавляем ключ -n

$ grep -vn '^$' test | sort -t':' -k2b -k1,1rn
27:aaaaaaaaaa
24:aaaaaaaaaa
26: bbbbbbbbb
22: bbbbbbbbb
23:  cccccccc
19:  cccccccc
20:   ddddddd
16:   ddddddd
18:    eeeeee
14:    eeeeee
15:     fffff
11:     fffff
12:      gggg
8:      gggg
10:       hhh
6:       hhh
7:        ii
3:        ii
4:         j
1:         j

Есть же! Вот теперь можно удалять дубликаты, но нужен ещё конвеер, увы

$ grep -vn '^$' test | sort -t':' -k2b -k1,1rn | sort -t':' -k2b -u
27:aaaaaaaaaa
26: bbbbbbbbb
23:  cccccccc
20:   ddddddd
18:    eeeeee
15:     fffff
12:      gggg
10:       hhh
7:        ii
4:         j

Переворачиваем поле с номерами строк (ещё конвеер, мда…)

$ grep -vn '^$' test | sort -t':' -k2b -k1,1rn | sort -t':' -k2b -u | sort -t':' -k1,1
10:       hhh
12:      gggg
15:     fffff
18:    eeeeee
20:   ddddddd
23:  cccccccc
26: bbbbbbbbb
27:aaaaaaaaaa
4:         j
7:        ii

Да блииин! Лексикографический, сцуко! Не забывай ключ -n!

$ grep -vn '^$' test | sort -t':' -k2b -k1,1rn | sort -t':' -k2b -u | sort -k1,1n
4:         j
7:        ii
10:       hhh
12:      gggg
15:     fffff
18:    eeeeee
20:   ddddddd
23:  cccccccc
26: bbbbbbbbb
27:aaaaaaaaaa

Фух, теперь можно убрать номера строк

$ grep -vn '^$' test | sort -t':' -k2b -k1,1rn | sort -t':' -k2b -u | sort -t':' -k1,1n | sed -E 's/^[0-9]+://'
         j
        ii
       hhh
      gggg
     fffff
    eeeeee
   ddddddd
  cccccccc
 bbbbbbbbb
aaaaaaaaaa

Ну, вот так вроде должно работать нормально.

Вот он, кровавый Unix Way!

file=$1
list=$(grep -vn '^$' $file |
       sort -t':' -k2b -k1,1rn |
       sort -t':' -k2b -u |
       sort -t':' -k1,1n |
       sed -E 's/^[0-9]+://')
echo "$list" > $file

С виду работает как надо, как ещё точнее проверить уже не знаю 😀