#bash
#bash
Вопрос:
У меня есть log.txt файл, который выглядит точно так же, как этот.
2.txt
/home/test/2.txt
имя файла, за которым следует его исходный путь, я хочу обновить этот журнал, чтобы удалить эти строки, когда этот конкретный файл будет удален. это фрагмент, который это делает.
if grep -Fxq "$var" log.txt
then
result=$(grep -m2 "$var" log.txt | tail -n1 )
mv $var $result
grep -w $var log.txt > log.txt.tmp
fi
первые две строки работают, они перемещают файл обратно
в исходный каталог.
эта строка здесь
grep -w $var log.txt > log.txt.tmp
помещает то, что я хочу удалить из log.txt во временный текстовый файл. Это неверно
Мне нужно удалить результат
grep -w $var log.txt > log.txt.tmp
из log.txt файл, но, похоже, я не могу этого сделать
Я пытался удалить одно и то же содержимое из двух файлов, но это слишком медленно, и я не хочу сортировать каждый раз. Должен быть более простой способ. Спасибо.
В основном вывод будет выглядеть следующим образом.
2.txt
/home/2.txt
3.txt
/home/3.txt
если они решат удалить 2.txt (который уже работает) новый log.txt файл будет
3.txt
/home/3.txt
Я думаю, что в основном нужно искать log.txt и удалите имя файла и строку под ним.
sed -i "/$var/d" log.txt
Я попробовал это, но он удаляет файлы с 1.txt в нем также, так что, если файл 11.txt это также устранит и это.
Комментарии:
1. Пожалуйста, добавьте желаемый результат для этого примера ввода в свой вопрос.
2. Итак
sed -i "/$var/d" log.txt
, IIUC3. @daniu, который работает, к сожалению, он удаляет файлы с похожими именами, такими как 11.txt потому что 1.txt есть в нем 🙁
4. Затем сделайте
sed -i "/^$var/d" log.txt
. Это заставляет имя файла начинаться с переменной. Или,sed -i "/^$var$/d" log.txt
чтобы сделать точное совпадение.5. @Anubis это также удалит каталог под именем файла? поскольку он содержит имя файла в пути?
Ответ №1:
if grep -Fxq "$var" log.txt
then
result=$(grep -m2 "$var" log.txt | tail -n1 )
echo mv $var $result
sed -i '/'"${var//./\.}"'$/d' log.txt # remove all the lines ending with $var value
fi
Обратите внимание, что в общем случае любые символы точки ( .
) в $var
должны быть экранированы, поскольку точка может совпадать с любым символом в совпадении регулярных выражений.
т. е. если $var=2.txt
, то sed -i '/2.txt/d' log.txt
совпадения и т.д. 2.txt
2atxt
..
${var//./\.}
предназначен для экранирования символов точки, чтобы избежать вышеуказанных совпадений.
Если путь к каталогу всегда следует за строкой с именем файла, в качестве альтернативы вы можете выполнить точное совпадение с именем файла и удалить обе строки следующим образом.
sed -i '/^'"${var//./\.}"'$/, 1 d' log.txt
Это может помочь, если у вас есть строки, заканчивающиеся одним и тем же именем файла, которые вам не нужно удалять.
Комментарии:
1. да, это не изменяет содержимое файла при выполнении команды sed. Я даже прогнал его через терминал.
2. вы
var
правильно установили переменную?3. да, var — это просто аргументы от пользователя, которые будут именами файлов, это просто в настоящее время для var в «$ @» do, который перебирает все аргументы в командной строке
4. Это должно работать в любой достаточно современной
sed
версии. Проверьте, печатает ли следующее1 4 5
(удаление2 3
):seq 5 | sed '/2/, 1 d'
5. Лол, это действительно работает, но его все еще удаляют 11.txt потому что технически это все еще заканчивается 1.txt очень досадная ошибка:(