#!/bin/bash set -o nounset set -o errexit set -o pipefail declare -r SCRIPT_DIR="$( cd "$( dirname "$" )" && pwd )" declare -r FILES_DIR=$ while read -r ONE_PATH do for ONE_FILE in $(find "$FILES_DIR" -maxdepth 1 -type f -print) do if [[ "$ONE_FILE" == *".swp" ]] || [[ "$ONE_FILE" == *"common.txt" ]]; then continue fi sed -i '\|^'"$ONE_PATH"'$|d' "$ONE_FILE" done echo "Done removing $ONE_PATH" done < "$SCRIPT_DIR"/../common.txt exit 0
sed: удаление списка путей из набора файлов
У меня есть файл с именем common.txt, который содержит список абсолютных путей. Например:
/etc /etc/group /var/log/syslog
У меня также есть набор файлов <hostname> .txt, которые также содержат список абсолютных путей. Вот пример (назовите его host1.txt ):
/root/.bashrc /var/log/syslog /etc/hosts /bin/true /etc /sbin/rtmon /etc/group
Я хотел бы удалить все пути, которые появляются в common.txt, из каждого файла в наборе файлов <filename> .txt . Итак, приведенный выше пример файла host1.txt :
/root/.bashrc /etc/hosts /bin/true /sbin/rtmon
Я написал следующий скрипт Bash для этого:
#!/bin/bash set -o nounset set -o errexit set -o pipefail while read -r ONE_PATH do for ONE_FILE in host1.txt host2.txt host3.txt do sed -i '\:'"$ONE_PATH"':d' "$ONE_FILE" done done < common.txt
Я испытываю трудности с получением правильной команды sed. То, что показано выше, приводит к тому, что все файлы оперируются, когда становятся пустыми.
Как я могу это исправить, чтобы достичь своей цели?
3 ответа на вопрос
Могу ли я предложить решение, которое не использует sed?
sort common.txt > common.txt.sorted for f in host1.txt host2.txt host3.txt ; do sort $f > $f.sorted diff common.txt.sorted $f.sorted | egrep '^>' | sed -e 's/^> //' > $f.output rm $f.sorted done
сортировка сортирует списки в алфавитном порядке. diff находит различия между файлом и common.txt . egrep выбирает строки, которые начинаются с >
, которые являются строками в host1.txt.sorted, но не в common.txt.sorted . Наконец, sed удаляет ведущий >
(за которым следует пробел), добавленный diff .
Список вывода также будет в алфавитном порядке.
Сначала вход должен быть отсортирован в обратном порядке. Бесполезно удалять / etc и затем искать / etc / group. Затем мы проверяем, можно ли записать файл (если не пропустить). Затем ONE_PATH должен быть экранирован, и тогда sed сможет выполнить свою работу,
sort -r common.txt \ | while read -r ONE_PATH do for ONE_FILE in host1.txt host2.txt host3.txt do if [ -w "$ONE_FILE" ] then # sed -i '\:'"$ONE_PATH"':d' "$ONE_FILE" ONE_PATH_ESC=$(echo "$ONE_PATH" | sed "s!/!\\\/!g") sed -i 's/^'"$ONE_PATH_ESC"'//' "$ONE_FILE" fi done done
С предоставленными тестовыми данными вы получите:
$ pr -n host1.txt 1 /root/.bashrc 2 3 /hosts 4 /bin/true 5 6 /sbin/rtmon 7
Есть 3 пустых строки.
Похожие вопросы
-
9
В чем разница между командами "su -s" и "sudo -s"?
-
4
Требуется хороший бесплатный образ Ubuntu Server VMWare
-
4
Каковы различия между основными дистрибутивами Linux? Я замечу?
-
-
2
Ограничить использование процессора для Flash в Firefox?
-
2
Как мне заставить мой микрофон работать под Debian GNOME?
-
2
Конки установки - образцы / идеи?
-
3
Каковы различия между оконными менеджерами Linux?
-
2
ThunderBird / Синхронизация освещения с SE k770i
-
4
Файловая система Linux
-
6
Полноэкранная медленная вспышка в KDE 4