Как я могу использовать файл в команде и перенаправить вывод в тот же файл без его усечения?


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

grep -v 'seg[0-9]{1,}.[0-9]{1}' file_name > file_name

однако, когда я это делаю, я получаю пустой файл. Есть мысли?

13 61

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

вместо этого используйте sed:

sed -i '/seg[0-9]\{1,\}\.[0-9]\{1\}/d' 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 / Vim
  • g/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

может быть, вы можете сделать это так:

grep -v 'seg[0-9]\{1,\}\.[0-9]\{1\}' file_name | cat > file_name