Унікальне сортування: перенаправлення виводу на той самий файл


14

Чи є якийсь короткий спосіб зберегти вихідний патрубок у той самий файл, який обробляється. Наприклад, саме цим я і займаюся

$ cat filename | sort | uniq > result
$ rm -f filename
$ mv result filename

Мені було цікаво, чи існує спосіб зробити це лише одним рядком (не додаючи ці команди за допомогою &&)

Це не шлях, а щоб отримати уявлення

$ cat filename | sort | uniq > filename

2
echo $(cat filename | sort | uniq > result) > filenameабо щось ? Просто проходячи повз, я не встигаю спробувати це.
MrVaykadji

Відповіді:


18

Ви можете використовувати spongeз пакету moreutils :

LC_ALL=C sort -u filename | sponge filename

Вам також не потрібна труба uniq, оскільки коли при сортуванні sortє -uможливість унікальних ліній.

Зауважте, що в системі GNU з локалями UTF-8 sort -uабо sort | uniqне давали вам унікальних ліній, але перші з послідовності рядків, які сортують однакові в поточному мові.

$ printf '%b\n' '\U2460' '\U2461' | LC_ALL=en_US.utf8 sort | LC_ALL=en_US.utf8 uniq

дав тобі тільки . Зміна локалі на C форсувати порядок сортування на основі байтових значень:

$ export LC_ALL=C
$ printf '%b\n' '\U2460' '\U2461' | LC_ALL=C sort | LC_ALL=C uniq


12

Вам не потрібна додаткова команда, як catі, uniqа також без використання rmкоманд і mvкоманд для видалення та перейменування імені файлу. просто використовуйте просту команду.

sort -u filename -o filename


 -u, --unique
        with -c, check for strict ordering; without -c, output only  the
        first of an equal run

 -o, --output=FILE
        write result to FILE instead of standard output

Як це працює?

sortкоманда сортує ваше ім'я файлу та за допомогою -uпараметра видаляє з нього повторювані рядки. потім за допомогою -oпараметра записує вихід у той самий файл методом in place.


3
Якщо система sortпрацює під час запуску, ви втратите свій оригінальний файл.
cuonglm

@Gnouc Отже, це кінець нещасливому !! : '(
αғsnιη

1
Спасибі! в цьому прикладі, особливо з «суровістю», я повинен це зробити. Однак я думав про загальний випадок. @Gnouc, ха-ха, немає жодного способу думати, що якби цього не сталося з тобою, правда?
whitenoisedb

3

Ваш запропонований приклад (нижче) не працює, оскільки ви насправді одночасно читали та записували в той самий файл.

$ cat filename | sort | uniq > filename

Ідея з трубою або переадресацією полягає в тому, що команда з лівої та правої сторони кожної труби або перенаправлення виконується одночасно, паралельно. Команда праворуч обробляє інформацію, коли вона передається їй від команди зліва, в той час як команда зліва все ще виконується.

Для того, щоб ваш сценарій працював, команду, що читає з файлу, потрібно було б виконати до того, як розпочнеться команда, що записує у файл. Для того, щоб це працювало, вам потрібно спочатку перенаправити висновок у тимчасове місце розташування, після чого після завершення відправте його з тимчасового місця назад у файл.

Кращий спосіб зробити це в основному, як у попередньому прикладі, коли ви перенаправляєте на тимчасовий файл, а потім перейменовуєте цей файл у початковий (за винятком того, що вам не потрібно спочатку видаляти файл, оскільки переміщення видаляє будь-яку існуючу ціль) .

$ cat filename | sort | uniq > result
$ mv -f result filename

Ви також можете зберегти його в рядковій змінній, за винятком того, що працює лише тоді, коли даних достатньо мало, щоб одразу вписатись у пам'ять.


Коли хтось викладений у запропонованій редакції, ви можете змінити cat filename | sortна просто sort filename- catтут непотрібно.
thomasrutter

Мій приклад нижче не був способом зробити це. Дякуємо за роз’яснення catв цьому випадку може бути непотрібним, але я зосереджувався на частині перенаправлення.
whitenoisedb

1
Я пояснював, чому ваш приклад нижче не працює. Я знаю, що ти знав, що це не працює.
thomasrutter

Дякуємо за уточнення! Насправді я не знав, що насправді відбувається.
whitenoisedb

2

Ви можете використовувати teeкоманду:

sort -u filename | tee filename > /dev/null

teeКоманда зчитує дані зі стандартного вводу і записує в стандартний висновок і файли.


2
Це не працює для мене.
pjvandehaar

3
Це не працює як askubuntu.com/a/752451
Стівен Пенні

Це справді працює для мене. наприклад, для переміщення рядка до нижньої частини файлу: (cat ~/file | grep -v 3662 ; printentry 3662) | tee ~/file > /dev/nullпрацює. Як і в оригінальній публікації, ця робота не працює, якщо ви просто > ~/fileбез цього tee. Тут схоже на трійник sort -o file, який записує у названий файл, не продовжуючи ту саму трубку.
Джошуа Голдберг

Зачекайте, вибачте! Я емпірично бачив, що це непередбачувано втратить дані, як пояснено у посиланні від @Steven. Складіть файл з цифрами 1..9 на 9 рядках. Далі буде працювати кілька разів, а потім періодично видаляти всі дані з файлу: (cat x | grep -v 7 ; echo 7) | tee x > /dev/null; cat x я рекомендую тимчасовий файл mvабо, можливо, рішення за посиланням @ Steven.
Джошуа Голдберг

@JoshuaGoldberg Ви бачили мою відповідь на цій сторінці?
Стівен Пенні

0

Ви можете використовувати Vim в режимі Ex:

ex -sc 'sort u|x' filename
  1. sort u сортувати унікальний

  2. x напишіть, чи були внесені зміни (вони були) та закрийте

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.