Как я могу использовать файл в команде и перенаправить вывод в тот же файл без его усечения?
в основном я хочу взять в качестве входного текста из файла, удалить строку из этого файла и сохранить результат обратно в тот же файл. Что-то вроде этого, если это делает его более ясным.
grep -v 'seg[0-9]{1,}.[0-9]{1}' file_name > file_name
однако, когда я это делаю, я получаю пустой файл. Есть мысли?
13 ответов:
вы не можете этого сделать, потому что bash сначала обрабатывает перенаправления, а затем выполняет команду. Поэтому к тому времени, когда grep смотрит на file_name, он уже пуст. Вы можете использовать временный файл.
grep -v 'seg[0-9]\{1,\}\.[0-9]\{1\}' file_name > tmpfile cat tmpfile > file_name
так, рассмотрите возможность использования
mktemp
создать tmpfile но обратите внимание, что это не POSIX.
использовать бисквит для такого рода задач. Ее часть более чем скромная.
попробуйте эту команду:
grep -v 'seg[0-9]\{1,\}\.[0-9]\{1\}' file_name | sponge file_name
попробуйте этот простой
grep -v 'seg[0-9]\{1,\}\.[0-9]\{1\}' file_name | tee file_name
на этот раз ваш файл не будет пустым :) и ваш вывод также будет напечатан на вашем терминале.
вы не можете использовать оператор перенаправления (
>
или>>
) в тот же файл, потому что он имеет более высокий приоритет, и он будет создавать/удалять файл перед командой даже ссылаться. Чтобы избежать этого, вы должны использовать соответствующие инструменты, такие какtee
,sponge
,sed -i
или любой другой инструмент, который может записывать результаты в файл (например,sort file -o file
).в основном перенаправление ввода в тот же исходный файл не имеет смысла, и вы должны использовать соответствующие Редакторы на месте для что, например Ex editor (часть Vim):
ex '+g/seg[0-9]\{1,\}\.[0-9]\{1\}/d' -scwq file_name
где:
'+cmd'
/-c
- выполнить любую команду Ex / Vimg/pattern/d
- удалить линии, соответствующие шаблону с помощью глобальные (help :g
)-s
- бесшумный режим (man ex
)-c wq
выполнить:write
и:quit
команды
вы можете использовать
sed
для достижения того же (как уже показано в других ответы), однако на месте (-i
) является нестандартным расширением FreeBSD (может работать по-разному между Unix / Linux) и в основном это stream Эдitor, а не редактор файлов. Смотрите:имеет ли режим Ex какое-либо практическое применение?
один лайнер альтернатива-установить содержимое файла в качестве переменной:
VAR=`cat file_name`; echo "$VAR"|grep -v 'seg[0-9]\{1,\}\.[0-9]\{1\}' > file_name
там же
ed
(в качестве альтернативыsed -i
):# cf. http://wiki.bash-hackers.org/howto/edit-ed printf '%s\n' H 'g/seg[0-9]\{1,\}\.[0-9]\{1\}/d' wq | ed -s file_name
вы можете использовать slurp с POSIX Awk:
!/seg[0-9]\{1,\}\.[0-9]\{1\}/ { q = q ? q RS : } END { print q > ARGV[1] }
Я обычно использую тройник для этого:
grep -v 'seg[0-9]\{1,\}\.[0-9]\{1\}' file_name | tee file_name
Он создает и удаляет tempfile сам по себе.
попробуй такое
echo -e "AAA\nBBB\nCCC" > testfile cat testfile AAA BBB CCC echo "$(grep -v 'AAA' testfile)" > testfile cat testfile BBB CCC
так как этот вопрос является лучшим результатом в поисковых системах, вот один лайнер от https://serverfault.com/a/547331 который использует подоболочку вместо
sponge
(который часто не является частью ванильной установки, такой как OS X):echo "$(grep -v 'seg[0-9]\{1,\}\.[0-9]\{1\}' file_name)" > file_name
или общий случай:
echo "$(cat file_name)" > file_name