История изменений
Исправление 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
С виду работает как надо, как ещё точнее проверить уже не знаю 😀