Уникальная сортировка: перенаправить вывод в тот же файл

14

Есть ли какой-нибудь короткий способ сохранить вывод канала в тот же файл, который он обрабатывает. Например, это то, что я на самом деле делаю

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

Мне было интересно, если есть способ сделать это в одну строку (не добавляя эти команды с помощью &&)

Это не способ, но чтобы получить представление

$ cat filename | sort | uniq > filename
whitenoisedb
источник
2
echo $(cat filename | sort | uniq > result) > filenameили что-то ? Просто проходя мимо, у меня нет времени, чтобы попробовать это.
Мр. Вайкаджи

Ответы:

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

cuonglm
источник
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параметром записывает вывод в тот же файл с методом на месте.

αғsнιη
источник
3
Если сбой системы во время sortработы, вы потеряете ваш оригинальный файл.
Cuonglm
@Gnouc Итак, это конец неудачи !! : '(
αғsнιη
1
Благодарность! в этом примере, особенно с «сортировкой», я должен это сделать. Однако я думал об общем случае. @ Gnouc, ха-ха, нет никакого способа думать, что если этого не случилось с тобой, верно?
whitenoisedb
3

Предлагаемый вами пример (ниже) не работает, потому что вы на самом деле читаете и пишете в один и тот же файл одновременно.

$ cat filename | sort | uniq > filename

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

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

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

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

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

thomasrutter
источник
Как кто-то внес в предлагаемое редактирование, вы можете изменить cat filename | sortпросто sort filename- catздесь не нужно.
Томасруттер
Мой пример ниже не был способом сделать это. Спасибо за разъяснение. catможет быть ненужным в этом случае, но я сосредоточился на части перенаправления.
whitenoisedb
1
Я объяснял, почему ваш пример ниже не сработает. Я знаю, что ты знал, что это не сработало.
Томасруттер
Спасибо за разъяснение! На самом деле я не знал, что на самом деле происходит.
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 написать, если изменения были сделаны (они есть) и выйти

Стивен Пенни
источник